What the application is for
SILKEN is a visual astronomy workspace for inspecting the same sky position across image surveys, catalogues, time-domain cutouts, and event footprints. It is aimed at astronomers who need to assemble and compare public or CANFAR-accessible data before moving into more specialised reduction or analysis tools.
It is not a replacement for a reduction pipeline or a data archive. It keeps the exploratory context around those systems together: sky position and field of view, visible imagery, catalogue queries and overlays, frame playback, plot state, job results, and links to the underlying products.
Choose data
Image Layers controls imagery and frame sequences. Catalogs queries Youcat, HATS, the CADC Archive, VO, GW, and other sources. Rubin DP1 and DP2 are CADC presets. Navigator keeps spatial context.
Inspect together
Pan, zoom, change projection, order the stack, style layers, inspect markers, and compare everything in one Aladin view.
Follow the evidence
Data holds result tables, Code supports reproducible work, Tools turns reviewed sources into reusable analysis, and Jobs tracks longer-running operations.
/arc/home/<cadc-user>/.silken/ and can be restored after compute is replaced.Connect code, create tools, and run reviewed revisions
GitHub and CANFAR Harbor are optional connections in Settings → Connections. GitHub uses a dedicated SILKEN OAuth App with authorization code, PKCE, and signed single-use state. The broad repo scope lets SILKEN inventory repositories that include private entries, but SILKEN uses it only for repository metadata and never requests workflow. Harbor accepts and validates an existing CLI secret; it never creates or rotates one.
Clone safely into ARC
Choose a public repository from the connected GitHub metadata list or enter any public HTTPS Git URL. Private entries are shown as unavailable because OAuth tokens never leave the BFF or enter a CANFAR runtime; place private code in ARC through an approved external workflow until an isolated clone broker is available. Public clones are shallow by default, asynchronous and cancellable, refuse collisions, and disable hooks, LFS downloads, submodules, redirects, embedded credentials, non-HTTPS protocols, and private-network targets.
Static, not generative
Python AST and a direct JavaScript parser rank package entrypoints, conventional CLIs, framework arguments, and exported functions. Repository code is not imported or executed. Every suggestion includes confidence, evidence, and editable inputs.
Immutable trust boundary
Workspace sources use a content hash, Git sources a commit SHA, and Harbor images a digest. Review the exact command, dependencies, mounts, network warning, and mappings. Trust never carries to a new revision.
Choose a workspace folder, managed Git checkout, or a public or connected private Harbor image carrying the CANFAR headless label.
Review ranked entrypoints, runtime, inputs, dependencies, warnings, outputs, and compatible execution modes. A repository may supply an authoritative silken-tool.yaml.
Bind scalars, ARC files or folders, durable Data tables, query/source-finding/crossmatch results, or sky regions through arguments, options, environment values, JSON stdin, or language function parameters.
Current-session and CANFAR headless runs isolate dependencies and logs. npm lifecycle scripts stay disabled unless explicitly enabled. Distributive is offered only for a statically proven self-contained JavaScript function.
Open declared outputs in Sky or Data, use completed Jobs as another tool input, update a source into a new untrusted revision, or prepare an editable COMET publishing project with the SILKEN OCI manifest label.
A short first workflow
Blank opens an empty workspace; Wizard prepares selected catalogues, measurements, and sky layers; Import products detects CARTA, Firefly, or Neloura outputs or lets you browse CANFAR storage before the viewer opens; Load restores a saved work session.
Enter a target name or coordinates in the top coordinate field and press Enter. Decimal degrees such as 44.5 +18.5 and sexagesimal coordinates are accepted.
Open Image Layers, search by survey, band, or source, and add one or more layers. Use opacity, blend, colour, and stack order to separate structures.
Choose a Catalogs sub-tab, prepare its query, and run it. Each catalogue tab retains its own query text, running request, saved queries, and result overlays when you move elsewhere.
Select table columns as sky overlays or profile plots, inspect rows in Data, and let the workspace autosave. Use the session menu to switch or delete work sessions.
A catalogue result does not recenter or change the zoom. Reposition the viewer explicitly when you want a different comparison field.
SILKEN user manual
Use this section as a compact map of the interface. Controls that are icon-only have a tooltip: hover the icon, or focus it with the keyboard, to see its name before using it.
| Task | Where | What to remember |
|---|---|---|
| Find a target | Coordinate field above the sky | Press Enter after a name or coordinate pair. The displayed field and current ICRS position are the default centre for epoch-image imports. |
| Manage image layers | Image Layers and the Stack panel | Group compact rows by source, band, type, or as one flat list; filter by source/band/type, and use Active only when needed. Sticky collapsed headers show total and active counts. Styling and expansion state are saved. |
| Query catalogues | Catalogs sidebar | Youcat, HATS, CADC Archive, VO, GW, alert, and file-backed tabs have independent query state and saved searches. CADC results also register automatically in Data. |
| Draw overlays or profiles | Overlay column controls | Use the first icon for an overlay/profile, then colour, then remove. Catalogue markers and footprints keep their own visibility and style. |
| Play epoch images | Import Epoch Images and the bottom Frame row | Choose an archive to load its frames immediately, then select all frames, every Nth frame, an evenly spaced count, or individual frames. A small decoded playback window stays in Aladin while the contributed runtime caches FITS bytes. |
| Export a frame sequence | Download menu beside playback | Export MP4, higher-quality WebM, or rendered FITS. Video captures the visible cutout area with current layers, overlays, footprints, opacity, blend, hue, and selected profile plots or legend. |
| Run analysis | Data, Code, and Jobs | Use session mode for short interactive work and headless/distributed jobs for longer operations. Job manifests and outputs remain in durable ARC storage. |
| Import or open another app | External-products toolbar icon | CARTA, Firefly, and Neloura provide tailored product filters and optional app shortcuts. Imported products merge through the same SILKEN layer, catalogue, region, or context pipeline. |
Start, restore, and preserve a workspace
| Feature | How to use it | Saved behaviour |
|---|---|---|
| Blank session | Choose Blank in Work sessions when you want the viewer without preselected data. | A new durable workspace is created after the start choice; startup metadata is reused rather than loaded again. |
| Setup wizard | Choose Wizard, then select source finding or cross-matching, science filters, measurements, catalogues, sky layers, and execution mode. Review the planned scope before Run. | The resulting queries, selected layers, target regions, and job references belong to the new work session. |
| Import products | Choose Import products, select CARTA, Firefly, or Neloura, then accept auto-detected returns or browse the storage locations offered for that tool. Confirm before the main app opens. | Returned images, tables, regions, and context enter the same workspace model as native SILKEN data. |
| Load saved session | Search the saved-session cards, open one, and wait for the dedicated restore progress to finish. Use the compact Start options control to return to the other choices. | Viewer position, layers and styles, query tabs, saved queries, overlays, profile panels, frame selection, and job references are restored. Epoch cutout URLs are refreshed before playback. |
| Session menu | Use the user menu to rename, switch, or delete work sessions. Deleting a session also removes its matching directory below .silken/workspace/sessions/. | Autosave records meaningful changes; wait for completion before closing after a large import or restore. |
Navigate the sky and manage imagery
| Feature | How to use it | Useful detail |
|---|---|---|
| Coordinate viewer | Choose the coordinate frame, enter a target name, decimal-degree pair, or sexagesimal pair, and press Enter. Drag to pan and use the wheel or +/- controls to zoom. | A numeric pair is applied directly; only a target name needs a resolver. Queries and imports do not recenter or change zoom. |
| Projection and view controls | Use the projection selector, fullscreen button, discovery-grid density, and viewer tool icons above the sky. The current centre and field of view remain under your control. | The legend and Stack panel can be kept open, moved through their own content, or closed without changing the plotted data. |
| Image Layers | Search or filter by provider, band, and type. Expand only the groups you need; search reveals matching groups temporarily. Open one row for styling, metadata, and actions. | Only expanded or matched groups render rows, keeping the public HiPS inventory responsive in a narrow sidebar. |
| Stack order | Open Stack to reorder or hide imagery, overlays, and catalogues. The list scrolls internally when it is longer than the viewer. | Order matters for opacity and blend calculations. Removing a layer also removes it from the stack and any matching frame-dataset selector. |
| Import image data | Select a local CANFAR FITS file, recursive directory, cube, or existing HiPS root. Review WCS footprints, compatible groups, exclusions, cube axes, and optional metadata/folder splits before import. | Small 2-D FITS images can stream directly; mosaics and derived cube products become cached HiPS layers. The detailed FITS/HiPS reference follows this manual. |
Query, visualize, and inspect catalogues
| Feature | How to use it | Useful detail |
|---|---|---|
| Catalog source tabs | Use Youcat, HATS, CADC Archive, VO Tables, GW Skymaps, Alerts, and Custom for their native query form. CADC offers guided filters, expert ADQL, and All CADC/Rubin DP1/Rubin DP2 presets. | Query text, running state, results, Overlay section, and saved searches are scoped to the source tab that created them. |
| CADC products | Expand a Plane result to resolve DataLink artifacts. Preview a bounded image/cube region, save that cutout, import the complete product, inspect FITS headers, or download a Plane package. | Discovery uses CADC TAP, artifacts resolve lazily through DataLink, cutouts use SODA, and complete artifacts/headers use the CADC Direct Data Service. Signed browser handles never contain CADC credentials. |
| Source Finder | Use the finder icon to open the same source-finding controls as the wizard: science area, use case, object/event types, measurements, provider, schema state, and catalog search. | Information icons summarize provider, tables, columns, coordinate capability, metadata status, provenance, and classification evidence. |
| Cross-match catalogues | Add one or more RA, Dec, radius, and tolerance rows, or import CSV, nested JSON, XLSX, or a public/link-shared Google Sheet. Confirm automatic column mapping in the preview. | The plan creates one job slice for every sky-region row and catalog-table combination. The first target row cannot be deleted. |
| Saved queries | Save a useful query from its catalogue tab and rerun it from that tab later. | Saved queries persist in the work session and never appear under a different catalogue source. |
| Overlay and profile controls | For a result column, choose Overlay/Profile, then colour, or remove. Scalars become encoded sky markers; array columns become profile curves. Hover a profile marker and lock its panel when you want it to remain. | Nested light curves use their matching time array when available. Query footprints and markers preserve their styles and do not alter the current view. |
| Data view | Open Data to switch among result tables, inspect columns and rows, save/reuse outputs, or pass a result to a tool. | Each completed query receives its own tab. Closing a visual overlay does not delete the underlying result table. |
Use time-domain imagery
| Feature | How to use it | Useful detail |
|---|---|---|
| Find epoch frames | Open the epoch importer from Image Layers. The toolbar starts with Select an archive...; a time-domain layer's frames icon preselects that archive. Frames load immediately at the current sky centre. | Use the dual MJD slider, one band, and maximum seeing to filter the already-visible chronological list. |
| Select frames | Choose Total count for evenly spaced sampling, All, Every N, or Choose with select-all/clear icons and individual cards. | The selection preview is chronological. Total count includes the first and last filtered epochs. |
| Frame player | Wait for the initial window to buffer, then drag the slider or use Play, loop, and FPS. When several sequences are loaded, select a dataset from the compact selector. | Frame position, FPS, and loop state are retained per dataset. Playback waits for each requested frame and keeps a bounded decoded browser window. A locked time-axis profile follows the active MJD and highlights its nearest sample. |
| Observation time | Read the time-domain timestamp beside Frame. The same observation panel can show a selected visible static layer; use its selector when more than one static layer has a date range. | Fixed-width timestamps prevent the bottom controls from shifting as the selected frame changes. |
| Video and FITS export | Open the download menu, select MP4, high-quality WebM, or rendered FITS, then place the optional legend and any plotted profile graphs in the four corners or four edge centres. | Rendered output captures the visible cutout, imagery, overlays, footprints, styling, and selected plots. Each of the eight positions accepts one element, and occupied positions are disabled for the others. |
Work with files, code, tools, and jobs
| Feature | How to use it | Useful detail |
|---|---|---|
| Navigator | Browse mounted personal and project ARC/Vault storage from the contributed CANFAR runtime. Open folders, inspect files, and select inputs without downloading directory listings through the public entry service. | Only paths mounted for the authenticated runtime are offered. Permission and missing-mount errors are distinct from service reconnection errors. |
| Code | Use the file browser/editor and terminal for short exploratory work in the current session. Save durable inputs and outputs under personal or project ARC paths. | The container filesystem and scratch space are temporary; session state references durable products rather than embedding large files. |
| Tools | Add a workspace folder, Git repository, or labelled Harbor image; inspect entrypoints, map inputs, review trust and resource settings, then run in the current session, CANFAR headless, or an eligible distributed mode. | Trust is tied to an exact content hash, commit SHA, or image digest. Updating a source requires a new review. |
| Jobs | Open Jobs to see owner, execution mode, state, slices, progress, age/runtime, resources, and output. Expand a row for logs, cancellation, retry, or product actions. | The table polls once per second only while Jobs is visible and refreshes immediately on return. User-triggered work is shown; the maintainer semantic snapshot job is not. |
| Execution modes | Use current-session mode for short interactive tasks, CANFAR headless for durable isolated jobs (the default for wizard plans), or Distributive only when the tool is proven compatible. | Large source-finding plans use one slice per catalog table; cross-matches use one slice per region row and catalog table, with bounded provider concurrency. |
Settings, handoffs, and common recovery actions
| Feature | How to use it | Useful detail |
|---|---|---|
| Connections and settings | Use the user menu to manage GitHub, Harbor, Rubin, display, and runtime-related settings. Follow connector prompts rather than entering credentials into a tool command. | CADC identity comes from the authenticated session; arbitrary tools never receive SILKEN control-plane secrets. |
| CARTA, Firefly, and Neloura | Use Continue with to launch a supported app or import returned products. Each branch shows only storage filters and products relevant to that application. | All three are importer/handoff choices in the same SILKEN runtime, not separate SILKEN images. |
| Retry a request | Keep a failed modal open, read its structured error, correct the source/inputs, and use Retry. Popups do not close on backdrop clicks. | During active work, dismiss controls are removed until success or an actionable failure is returned. |
| Slow or disabled playback | Wait for the initial playback window or reduce the cutout size. A larger contributed-session memory allocation permits a larger raw-FITS cache, while network and decoding speed still bound first access. | GPU launch resources do not accelerate remote TAP queries or Aladin's browser WebGL renderer; server-side CPU and RAM help runtime staging and cache reuse. |
| Missing restored data | Look for stale/unavailable badges, confirm that the referenced ARC path still exists, and use the repair/re-import action. | SILKEN keeps the saved entry visible so the missing dependency is explicit rather than silently dropping it. |
Search in astronomers’ language
Choose a science area, analysis use case, concrete Object / event type, and measurements. Catalogs can carry several object/event labels, including Type Ia supernovae, neutron stars, and binary black-hole mergers. Source finding does not need a cone centre.
Compare one or many regions
Add as many RA, Dec, search-radius, and match-tolerance rows as needed; the first row always remains. CSV, nested JSON, XLSX, and public or link-shared Google Sheets imports include automatic column mapping, a preview, and first-invalid-cell reporting before Apply.
- Use a descriptive work-session name before building a large comparison; saved sessions are easiest to distinguish by name and last-save time.
- Keep generated products in personal or project ARC paths. Treat
/scratchand the container filesystem as temporary. - If an image obscures catalogue markers, lower its opacity, change blend mode, move it in the Stack panel, or temporarily hide it.
- For smooth playback, wait for the initial frame window before pressing Play. SILKEN bounds the decoded browser window and caches normalized FITS bytes in the contributed CANFAR runtime; larger session RAM can increase that cache, while GPU allocation is reserved for server-side workloads that explicitly support it.
Import FITS images, cubes, mosaics, and existing HiPS
Use Import image data in Image Layers to choose one FITS file, an existing HiPS root, or a directory tree. Inspection runs inside the contributed CANFAR session, so mounted ARC and user storage are read directly. Only roots that are actually mounted in that runtime are offered for image import; a remotely browsable path is not mistaken for a locally importable source. The scan opens headers lazily and does not read every pixel just to identify the products.
A tiled sky product
A HiPS root has a properties metadata file, Norder<n> tile hierarchy, and Moc.fits coverage map. SILKEN validates and links that existing product immediately; it does not rebuild it.
An image or data cube
Ordinary FITS files do not need a HiPS properties file. Placement comes only from a valid celestial WCS in each image HDU. Files without usable WCS are excluded with the file, HDU, and relevant header reason.
Supported names are case-insensitive .fits, .fit, .fts,
.fits.gz, .fit.gz, and .fz. Every image HDU in a multi-extension file is
considered. SILKEN records celestial frame, footprint, projection, pixel scale, axes, filter or frequency,
epoch, unit, beam, exposure, product role, and the evidence used for inferred classifications. Filename clues
can identify masks, weights, PSFs, noise maps, or moments, but filenames are never used to guess a sky position.
Nested directories are crawled recursively, symbolic-link cycles and generated .silken products
are skipped, and unreadable branches or scan limits are listed explicitly in the review.
What the review means
| Case | Import behaviour | Scientific caution |
|---|---|---|
| One 2-D HDU, at most 128 MiB | Displayed directly through an authenticated, byte-range-capable FITS endpoint. | The source remains authoritative; changing or removing it marks the saved layer stale or unavailable. |
| Many images or a large image | Compatible images are grouped and Hipsgen creates persistent tiles, properties, previews, and MOC coverage. | Overlaps use a NaN-aware mean. A common positive exposure keyword is passed to Hipsgen for exposure normalization. |
| Spectral, time, or Stokes cube | Select a plane, a range reduced by mean, sum, maximum, or width-aware moment 0, or a supported regular whole cube. Select Stokes explicitly when present. | A rendered plane or mosaic is a visualization product, not an undeclared calibrated coadd. |
| Mixed collection | Groups split when observable, band or frequency, Stokes, unit, epoch semantics, dimensionality, frame, role, or resolution are incompatible. | Masks, weights, PSFs, and noise products are associated with science groups but start unselected. |
CTYPE, CRPIX, CRVAL, and CD or CDELT/PC headers. SILKEN will not silently place an image whose astrometry is absent or invalid. See the FITS WCS references and the IVOA HiPS specification.FITS collections have no universal required directory layout. Archives commonly arrange files by target, observation, band, epoch, pointing, tile, or pipeline product; the recursive scanner does not depend on one of those conventions. It uses headers to group compatible data and shows the proposed groups and footprints before import without moving the current Aladin centre or zoom.
Combine compatible is the default. The review can additionally split the saved header manifest by band, observable, product role, unit, epoch, Stokes, HDU, cube-axis type, or resolution, and by a chosen relative-folder depth or leaf folder. These controls can be combined. Regrouping is immediate because it never rereads FITS headers. A Back icon abandons the inspection and restores the previous path, selected item, filter, sort direction, and scroll position.
Image-layer badges describe the evidence that exists: Survey image, Single epoch, Multi-epoch image, Epoch sequence, or a time, spectral, polarization, distance, or generic data cube. A broad survey HiPS such as ZTF DR7 is a survey/coadded image; archive cutouts imported as a frame sequence are the playable time-domain product. SILKEN does not infer cadence from a dataset name.
Inspection manifests, fingerprints, exclusions, provenance, prepared assets, and generated HiPS products are
cached below /arc/home/<cadc-user>/.silken/layers/ by default. Re-importing unchanged inputs and
settings reuses the existing product. Large builds appear in Jobs with staging, indexing, tiling, validation,
and registration progress. Saved sessions restore the registered layer; a changed or missing source remains in
the sidebar with a repair or re-import action instead of disappearing.
How comprehensive catalog discovery works
The setup wizard searches a durable semantic index rather than downloading every table and column into the
browser. The public part is refreshed nightly from configured HATS and Youcat sources, curated CADC/Rubin/
multimessenger descriptors, and TAP services published through the IVOA Registry. If RegTAP lacks a schema,
SILKEN records the gap and attempts a bounded direct VOSI or TAP_SCHEMA read. Administrative
registry schemas are indexed for coverage accounting but hidden by default.
Metadata, not result rows
Search, filters, catalog counts, column tags, capabilities, and provenance come from the cached SQLite/FTS snapshot. Running a selected query still contacts the provider and can take much longer.
Your visible Youcat schemas
Credential-visible Youcat metadata is cached separately for the current access context and merged over the public snapshot. A transient metadata failure does not erase the last usable schema.
Science area is a broad discipline, science use case describes the intended analysis, and Object / event type names the physical source or event. Object/event tags are multi-label. Science-area matching also follows use-case membership, so DESI and other redshift tables remain discoverable under Cosmology & Large-scale Structure even when their broad display group is galaxies.
Coverage labels
| Label | Meaning | Effect |
|---|---|---|
| n columns | The provider schema was loaded. A multi-table resource is summarized as m tables · n columns; unmatched fields still receive other. | The info icon shows measurement coverage, science and object/event tags, access, provenance, and freshness without expanding the selection row. |
| Partial schema | Some metadata is usable, or a last-good schema is being retained after a refresh failure. | Inspect provenance and warnings before a large run. |
| Schema pending | The catalog is known but its column metadata has not yet been published or retrieved. | It remains visible as a coverage gap; schema-dependent execution waits for metadata. |
| Metadata unavailable | The provider explicitly failed or does not expose usable schema metadata. | The catalog is reported, never misleadingly shown as “0 classified columns.” |
Source finding can include scientific tables without sky coordinates. Cross-match mode filters to catalogs with a usable RA/Dec pair. The default selection means all catalogs matching the current filters plus any explicit inclusions and minus exclusions, so a registry-scale plan does not require thousands of browser checkboxes. SILKEN shows the estimated catalogs, providers, metadata gaps, and unbounded-row warning and requires confirmation before execution.
Query slices and execution
A source-finding plan creates one provider-query slice per selected catalog table. A cross-match plan creates one slice for every sky-region row and catalog-table combination; results are grouped by region before any pair matching, so positions and tolerances never leak between imported rows. The wizard reports this slice count before the user confirms the run.
CANFAR headless
Queues durable asynchronous work with manifests, progress, logs, and results below the user’s .silken/jobs directory.
Distributive headless
Uses the configured distributed executor for row-processing slices while retaining the same provider-query boundaries.
This session
Runs serial or threaded work inside the contributed SILKEN runtime; use it for smaller requests that should finish quickly.
For private Google Sheets, download an XLSX copy and use the XLSX importer. SILKEN does not ask the browser for a separate Google credential.
Import examples: valid cross-match CSV · invalid CSV that first fails at C4.
Launch SILKEN from the CANFAR Science Portal
Sign in to the CANFAR Science Portal
and use Launch New Session. SILKEN is a contributed web application, so choose
contributed, not notebook. The image already contains the required
/skaha/startup.sh and serves the application on port 5000.
Standard tab
| Portal field | Value | Note |
|---|---|---|
| type | contributed | Selects the custom web-application routing contract. |
| image registry | images.canfar.net | The CANFAR Harbor registry. |
| project | candiapl | The image namespace. |
| container image | silken:latest | Use an immutable version tag instead of latest when reproducing a published workflow. |
| session name | For example, silken-demo3 | Any short, unique, descriptive name is fine. |
| resources | Flexible, or Fixed: 2 CPU, 8 GB RAM, 0 GPU | Flexible is the SILKEN default. Choose Fixed when the workload needs a predictable allocation. |
If candiapl / silken is not offered in the Standard image selectors, use Advanced. The Standard list depends on the registry inventory visible to the portal.
Advanced tab
| Portal field | Value | Note |
|---|---|---|
| container image registry | images.canfar.net | Choose the registry in the left part of the image field. |
| image path and tag | candiapl/silken:latest | Enter this in the image field to the right of the registry. |
| repository username | Leave blank for a public image | Only supply a Harbor pull identity when the selected tag is private. |
| repository secret | Leave blank for a public image | Use a Harbor pull token or robot secret when required—never a CADC account password. |
| type | contributed | This is required even though the image contains the startup script. |
| session name | For example, silken-demo3 | Use a name that distinguishes this runtime from saved SILKEN workspaces. |
| resources | Flexible, or Fixed: 2 CPU, 8 GB RAM, 0 GPU | Increase memory only for unusually large interactive products. |
The portal pulls the image, mounts CANFAR storage, and starts the contributed service. The first pull of a new tag can take longer than a reused image.
Use the connect/open action on the session card. SILKEN appears directly under the authenticated CANFAR session URL.
After application loading, choose Blank, Wizard, Import products, or a saved work session. Application workspaces and generated results remain in your mounted ARC home or project storage.
CANFAR’s contributed-application contract and troubleshooting guidance are maintained in the official contributed applications guide.
A gateway in front of replaceable compute
The public endpoint and the application process have different lifetimes. The gateway is inexpensive and continuously reachable. The application process is created for a user, receives mounted storage and identity, and can be destroyed when it is idle.
Compute can disappear without taking user state, job manifests, or results with it.
Use this pattern when
- each user needs isolated compute or data permissions;
- the app benefits from being close to mounted research data;
- idle compute should be reclaimed;
- work must resume in a later session.
Keep a service running when
- one shared backend serves all users efficiently;
- startup latency is unacceptable;
- the process owns continuous schedulers or inbound events;
- local process memory is itself durable state.
The request lifecycle
Exchange user credentials or an identity assertion for a short-lived platform token. Keep secrets server-side.
Reuse a healthy compatible session; otherwise request compute with the application image, resources, startup command, and environment.
The scheduler mounts storage, starts the container, and returns a private connection URL after the HTTP service becomes ready.
The gateway forwards API calls to the correct user session and adds a private service-to-service credential.
State and results go to mounted durable storage. Session expiry removes compute capacity, not the saved work.
The session type describes the interface
“Interactive session” does not imply a notebook. The selected session type is a routing and startup contract. A custom web-application session can run any HTTP application as long as its image satisfies that contract.
| Session class | Expected interface | Custom full web app |
|---|---|---|
| Notebook | Notebook server and notebook-specific routing | No |
| Specialized viewer | A named application such as an image or catalog viewer | No |
| Contributed / custom application | Arbitrary HTTP service with a documented startup path and port | Yes |
| Headless / batch | A command that runs to completion without a browser interface | For background work |
name=application-user-unique-id
image=registry.example.org/team/application:immutable-tag
type=custom-web-application
command=/platform/startup.sh
environment=APP_HOST=0.0.0.0
environment=APP_PORT=<platform-web-port>
# The process stays in the foreground and answers a health endpoint.
Publish registry discovery metadata separately
Container configuration labels and registry artifact labels serve different consumers. An image can declare its runtime interface in its Docker configuration while a platform discovers eligible images through a separate Harbor artifact label. Making a project public only permits pulls; it does not attach a discovery label, and a project-scoped label is not a substitute when the platform expects an existing global label.
Query Harbor labels with scope=g and the configured label name. Resolve the numeric ID at publication time because it belongs to the registry, not the application.
Resolve the pushed immutable tag to its digest, then post {"id": <resolved-global-label-id>} to that digest's artifact-label endpoint. Repairing a missing label does not require an image rebuild.
Read the artifact with with_label=true through the digest, immutable tag, release tag, and latest. Require the same digest and the expected global label on each reference.
artifact-label:create plus only the artifact and
repository read permissions required for verification. Store its generated name and secret as repository
secrets such as HARBOR_LABEL_USERNAME and HARBOR_LABEL_PASSWORD, never a personal
account password. A maintainer-only repair can instead use an authenticated Harbor browser session and its
CSRF token when that registry supports the flow.Create a project robot
A project robot is a non-human Harbor identity whose permissions stop at one project. It lets deployment
automation maintain discovery metadata without inheriting a maintainer's account privileges. In Harbor,
open Projects → <project> → Robot Accounts → New Robot, choose a descriptive name such
as <application>-github-labeler, and set an expiration that is monitored and rotated.
- Grant Artifact Label: Create (
artifact-label:create). - Grant Artifact: Read/List and Repository: Pull/List so the workflow can resolve and verify the artifact.
- Do not grant repository push/delete, scanner, project-admin, or system permissions.
- Copy the generated username and secret immediately. Harbor prefixes the username, for example
robot$<project>+<application>-github-labeler, and shows the generated secret only once. - Save the values as repository secrets
HARBOR_LABEL_USERNAMEandHARBOR_LABEL_PASSWORD. - Run the repository's label-only workflow against an existing tag before relying on the credential for a release.
For rotation, create or refresh the robot credential, update both repository secrets, pass the label-only workflow, and only then retire the previous credential. Never place either generated value in source, workflow YAML, logs, or documentation.
gh secret set HARBOR_LABEL_USERNAME --repo OWNER/REPOSITORY
gh secret set HARBOR_LABEL_PASSWORD --repo OWNER/REPOSITORY
import os
from urllib.parse import quote
import requests
api = os.environ["HARBOR_API"].rstrip("/")
project = os.environ["HARBOR_PROJECT"]
repository = os.environ["HARBOR_REPOSITORY"]
reference = os.environ["HARBOR_REFERENCE"] # immutable release or commit tag
label_name = os.environ["HARBOR_LABEL"]
auth = (os.environ["HARBOR_LABEL_USERNAME"], os.environ["HARBOR_LABEL_PASSWORD"])
# Resolve the existing global label. Never hard-code its registry-owned ID.
found = requests.get(
f"{api}/labels",
auth=auth,
params={"scope": "g", "name": label_name, "page_size": 100},
timeout=30,
)
found.raise_for_status()
label = next(item for item in found.json() if item["scope"] == "g" and item["name"] == label_name)
root = f"{api}/projects/{quote(project, safe='')}/repositories/{quote(repository, safe='')}/artifacts"
artifact = requests.get(f"{root}/{quote(reference, safe='')}?with_label=true", auth=auth, timeout=30)
artifact.raise_for_status()
digest = artifact.json()["digest"]
attached = requests.post(
f"{root}/{quote(digest, safe='')}/labels",
auth=auth,
json={"id": int(label["id"])},
timeout=30,
)
if attached.status_code not in (200, 201, 409): # 409 means already attached
attached.raise_for_status()
for verify_reference in (digest, reference, "latest"):
checked = requests.get(
f"{root}/{quote(verify_reference, safe='')}?with_label=true",
auth=auth,
timeout=30,
)
checked.raise_for_status()
payload = checked.json()
assert payload["digest"] == digest
assert any(item["scope"] == "g" and item["name"] == label_name for item in payload["labels"])
{"1":"carta","2":"desktop","3":"desktop-app","4":"notebook","5":"headless","8":"contributed","11":"firefly"}
External references
Persist state outside the session
A container filesystem, temporary directory, or in-memory session store is not a durable workspace. Store user-visible state under a mounted home or project directory and make the writes resilient to interruption.
Capture intent
Save selections, views, queries, references, and settings—not an opaque process snapshot.
Write atomically
Write a temporary file, flush it, and rename it into place so readers see an old or new complete value.
Rebuild safely
Version the state format, tolerate missing resources, and migrate older layouts without deleting them first.
payload = json.dumps(state).encode("utf-8")
temporary = state_path + ".tmp"
write_bytes(temporary, payload)
rename(temporary, state_path) # atomic within one filesystem
A replacement test is the strongest proof: save recognizable work, terminate the compute session, create another one, and restore from the same mounted path.
How SILKEN applies the pattern
SILKEN is an astronomy workspace for progressive image layers, catalogs, crossmatching, cutouts, and multimessenger data. Its public shell and scientific runtime are deliberately separate.
Arbutus BFF + Redis
The portal-hosted entry is the SILKEN Backend for Frontend (BFF): a small public service designed specifically for the web interface. It serves the browser shell, starts CADC OIDC through MMP, resumes or launches the matching CANFAR runtime, and securely proxies browser API requests to that private runtime. SILKEN never receives an account password, and access tokens, CANFAR connection details, and the scientific API stay out of browser code.
Why Redis? Process memory cannot be the source of truth for an authenticated route across service restarts. The signed browser cookie carries only an opaque session ID; Redis gives the BFF a short-lived server-side record containing the CADC identity and access token, CANFAR backend ID and connect route, private runtime secret, expiry, and per-user launch lock.
This shared record lets a new worker or rolling deployment recover the route, reattach the browser to the same runtime, and prevent duplicate launches. TTLs remove stale records automatically. During a hosted Redis interruption, authenticated operations fail closed instead of trusting process-local state that could diverge from logout or session rotation. Redis is deliberately an ephemeral control plane: saved sessions, layers, and job results remain durable under /arc/home/<cadc-user>/.silken/.
CANFAR runtime
Runs the private Python API close to mounted ARC data as a per-user Skaha contributed session.
Two supported entry paths
The portal entry sends the browser to the MMP-owned CADC OIDC flow. If CADC already has an identity session, that step completes without another prompt. SILKEN then shows the signed-in username and resource controls; Flexible asks CANFAR to assign resources, while Fixed accepts 1–16 CPU cores, 1–192 GB RAM, and zero or one GPU.
A user already authenticated through CADC OIDC in the CanDIAPL Multi-Messenger Portal launches SILKEN from MMP. The browser carries only a one-minute, single-use opaque launch code and a matching one-minute HTTP-only binding cookie. SILKEN submits both during server-to-server redemption, validates that the handoff was issued specifically for SILKEN, removes the code from the browser URL, clears and never persists the binding, skips only the identity prompt, and still asks the user to confirm the resource profile before it resumes or provisions CANFAR.
Use another account deliberately opens the CADC account chooser. Sign out of SILKEN clears the local pending identity; it does not claim to terminate every CADC identity-provider session in other tools.
Container and launch contract
The contributed image advertises its type, installs an executable startup script, and serves HTTP on CANFAR’s contributed-application port.
LABEL ca.nrc.cadc.skaha.type="contributed"
COPY scripts/silken-backend-startup /skaha/startup.sh
RUN chmod +x /skaha/startup.sh
ENV HIPS_SERVER_HOST=0.0.0.0
ENV HIPS_SERVER_PORT=5000
EXPOSE 5000
CMD ["/skaha/startup.sh"]
name=silken-<user>-<unique-suffix>
image=images.canfar.net/candiapl/silken:latest
cores=2
ram=8
type=contributed
The BFF lists existing type=contributed sessions with the user-specific SILKEN prefix. It
re-enters one only after checking health, version, and required capabilities; otherwise it replaces it. A
per-user launch lock prevents duplicate backends. Skaha uses the image command and injects the authenticated
user, session ID, and mounted home; contributed launches do not accept caller-supplied command or environment fields.
Private proxy boundary
Browser requests remain on the public origin. The BFF keeps Skaha’s connect URL server-side and adds
X-SILKEN-Session-Secret and the authenticated username when forwarding a request. The private
runtime rereads an owner-bound record in
/arc/home/<cadc-user>/.silken/backend-secrets/ for every protected request. The BFF writes,
rotates, and deletes that record through authenticated ARC operations; it never places the secret in the
contributed launch form.
Saved workspaces in .silken
The interactive container is ephemeral. SILKEN stores restorable work in the user’s mounted home directory, so a later or replacement runtime sees the same files.
The workspace state includes the sky view, active layers, query tabs, ADQL, overlay settings, time-domain controls, tab order, HATS state, CADC search/provenance state, and multimessenger state.
The browser serializes versioned state after meaningful changes, with a short debounce.
Arc browsing, file access, and durable writes use the filesystem mounted directly in the contributed CANFAR session. The hosted BFF uses SFTP only as a recovery path. Vault uses a local mount when the runtime exposes one and otherwise falls back to VOSpace.
A later runtime reads the session index and restores the selected SILKEN workspace. Pre-cutover application state is intentionally not imported.
Import products from CARTA, Firefly, or Neloura
The viewer toolbar has one compact external-products icon. The source choice tailors discovery and filters: CARTA focuses on radio images, spectral cubes, and regions; Firefly on catalogues, tables, survey images, and Vault products; Neloura on FITS images/cubes and catalogue files. The choice is provenance and browsing context only. Every product enters the same SILKEN installer and becomes an ordinary layer, catalogue, or region.
Whole workspace
Sky centre and FOV, ordered layers, queries, filters, selections, regions, styling, and provenance are written into a tool-neutral manifest.
One SILKEN runtime
All browsing, copying, parsing, and installation runs in candiapl/silken:<release-or-latest>. There are no source-specific SILKEN repositories, tags, or images.
Merge safely
New images, tables, regions, and view context appear behind a badge, are preselected, and import as new layers or tabs without replacement.
Files already available in personal or project ARC storage stay referenced in place. Catalogues use VOTable, images and cubes use FITS, and regions use DS9 where conversion is needed. Compute remains running after a return. The source-application shortcut can reopen, start, or stop the official CANFAR application when needed.
candiapl/silken:<release-or-latest> runtime. Only an explicit Open application
action starts one of those independent applications with its own official image. That image is not an importer
image, a SILKEN variant, or an alternative SILKEN tag.Interactive coordination, headless execution
The contributed session handles responsive API work. Large generation, indexing, source-finding,
crossmatch, and cutout operations can run in CANFAR headless sessions or through the configured
distributed executor.
Session mode
Serial or threaded work in the user’s current contributed runtime. Best for smaller requests that benefit from immediate feedback.
CANFAR headless
A separate headless run completes asynchronously. Manifests and results are exchanged through persistent ARC paths.
Distributive
Provider queries keep their catalog/region slice identities, while large returned row sets can be subdivided across configured workers.
Because jobs persist their manifest, progress, log, result, retry, and cancellation state under
.silken/jobs, the Jobs view does not depend on one Python process staying alive.
The Jobs tab is a compact live queue view with state, backend, progress, elapsed time, and current phase. It refreshes once per second while visible, pauses network polling when the user leaves the tab, and refreshes immediately on return. Infrastructure-owned semantic snapshot refreshes use the deployment workflow and never appear in a user’s Jobs tab.
Deployment and replacement checks
- The contributed image satisfies the provider-neutral registry-publication contract described in Architecture.
/skaha/startup.shis executable and leaves the server in the foreground.- The runtime binds
0.0.0.0:5000and answers/healthz. - The browser cannot see CADC tokens, Harbor credentials, private keys, connect URLs, or backend secrets.
- Saved state resolves beneath
/arc/home/<user>/.silken, not/tmpor/opt. - A brand-new contributed session restores a workspace saved by the previous session.
- Heavy jobs use persistent manifests and do not block the interactive API process.
- The single SILKEN importer path and each optional official CARTA, Firefly, and Neloura launch action pass authenticated CANFAR acceptance before the feature flag is enabled by default.
docker image inspect images.canfar.net/candiapl/silken:latest \
--format '{{ index .Config.Labels "ca.nrc.cadc.skaha.type" }}'
# expected: contributed
curl --fail http://127.0.0.1:5000/healthz
test -d "/arc/home/$USER"
find "/arc/home/$USER/.silken" -maxdepth 4 -type f -print
Implementation map
DockerfileDockerfile.canfarscripts/silken-backend-startupsilken_bff.pyscripts/serve.py and workspace_sessions.pyviewer/index.htmlscience_handoffs.py