Astronomer reference

A practical reference for working in SILKEN.

SILKEN combines an interactive sky, progressive image layers, catalog queries, time-domain frames, overlays, and CANFAR-backed analysis in a restorable browser workspace. This page covers day-to-day use, direct Science Portal launch, and the implementation details needed to operate it.

01LocateEnter coordinates or a target name, then keep the sky at the view you choose.
02CombineLayer surveys, frame sequences, catalog results, regions, and multimessenger footprints.
03ContinueSave the whole workspace, run analysis, or exchange products with CARTA, Firefly, and Neloura.
Using SILKEN

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.

Left sidebar

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.

Sky workspace

Inspect together

Pan, zoom, change projection, order the stack, style layers, inspect markers, and compare everything in one Aladin view.

Main tabs

Follow the evidence

Data holds result tables, Code supports reproducible work, Tools turns reviewed sources into reusable analysis, and Jobs tracks longer-running operations.

Persistence rule: a work session is an autosaved workspace, not the lifetime of one container. Important state is stored below /arc/home/<cadc-user>/.silken/ and can be restored after compute is replaced.
Using SILKEN

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.

Code

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.

Inspect

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.

Run

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.

1
Source.

Choose a workspace folder, managed Git checkout, or a public or connected private Harbor image carrying the CANFAR headless label.

2
Inspect and configure.

Review ranked entrypoints, runtime, inputs, dependencies, warnings, outputs, and compatible execution modes. A repository may supply an authoritative silken-tool.yaml.

3
Map inputs.

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.

4
Review and run.

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.

5
Reuse.

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.

Credential boundary: GitHub, Harbor, CADC, Flask, Redis, and registry credentials never enter arbitrary tool commands, environments, manifests, logs, or outputs. Public SILKEN images are launched without registry credentials; a connected user's Harbor credential is attached only to the single validated private-image pull request. Hosted interactive sessions do not receive shared Distributive billing credentials, so Distributive execution is disabled there until an isolated submission broker is available.
Using SILKEN

A short first workflow

1
Choose how to begin.

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.

2
Set the sky position.

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.

3
Add imagery.

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.

4
Query a catalogue.

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.

5
Inspect and save.

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.

Using SILKEN

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.

TaskWhereWhat to remember
Find a targetCoordinate field above the skyPress Enter after a name or coordinate pair. The displayed field and current ICRS position are the default centre for epoch-image imports.
Manage image layersImage Layers and the Stack panelGroup 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 cataloguesCatalogs sidebarYoucat, 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 profilesOverlay column controlsUse the first icon for an overlay/profile, then colour, then remove. Catalogue markers and footprints keep their own visibility and style.
Play epoch imagesImport Epoch Images and the bottom Frame rowChoose 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 sequenceDownload menu beside playbackExport 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 analysisData, Code, and JobsUse 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 appExternal-products toolbar iconCARTA, 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

FeatureHow to use itSaved behaviour
Blank sessionChoose 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 wizardChoose 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 productsChoose 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 sessionSearch 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 menuUse 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

FeatureHow to use itUseful detail
Coordinate viewerChoose 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 controlsUse 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 LayersSearch 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 orderOpen 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 dataSelect 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

FeatureHow to use itUseful detail
Catalog source tabsUse 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 productsExpand 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 FinderUse 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 cataloguesAdd 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 queriesSave 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 controlsFor 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 viewOpen 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

FeatureHow to use itUseful detail
Find epoch framesOpen 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 framesChoose 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 playerWait 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 timeRead 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 exportOpen 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

FeatureHow to use itUseful detail
NavigatorBrowse 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.
CodeUse 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.
ToolsAdd 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.
JobsOpen 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 modesUse 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

FeatureHow to use itUseful detail
Connections and settingsUse 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 NelouraUse 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 requestKeep 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 playbackWait 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 dataLook 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.
Source finding

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.

Cross-matching

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 /scratch and 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.
Image data reference

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.

HiPS

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.

FITS

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

CaseImport behaviourScientific caution
One 2-D HDU, at most 128 MiBDisplayed 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 imageCompatible 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 cubeSelect 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 collectionGroups 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.
Required WCS: a renderable HDU needs a two-dimensional celestial transformation, normally expressed by 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.

Catalog reference

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.

Instant discovery

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.

Authenticated overlay

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

LabelMeaningEffect
n columnsThe 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 schemaSome metadata is usable, or a last-good schema is being retained after a refresh failure.Inspect provenance and warnings before a large run.
Schema pendingThe 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 unavailableThe 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.

Default

CANFAR headless

Queues durable asynchronous work with manifests, progress, logs, and results below the user’s .silken/jobs directory.

Distributed

Distributive headless

Uses the configured distributed executor for row-processing slices while retaining the same provider-query boundaries.

Interactive

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.

What “exhaustive” means here: every catalog and column exposed by configured providers and public RegTAP/VOSI/TAP_SCHEMA metadata is retained. A service that is offline, access-restricted, or does not publish metadata is listed as an explicit gap; SILKEN cannot infer columns that a provider never exposes.
Walkthroughs

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 fieldValueNote
typecontributedSelects the custom web-application routing contract.
image registryimages.canfar.netThe CANFAR Harbor registry.
projectcandiaplThe image namespace.
container imagesilken:latestUse an immutable version tag instead of latest when reproducing a published workflow.
session nameFor example, silken-demo3Any short, unique, descriptive name is fine.
resourcesFlexible, or Fixed: 2 CPU, 8 GB RAM, 0 GPUFlexible 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 fieldValueNote
container image registryimages.canfar.netChoose the registry in the left part of the image field.
image path and tagcandiapl/silken:latestEnter this in the image field to the right of the registry.
repository usernameLeave blank for a public imageOnly supply a Harbor pull identity when the selected tag is private.
repository secretLeave blank for a public imageUse a Harbor pull token or robot secret when required—never a CADC account password.
typecontributedThis is required even though the image contains the startup script.
session nameFor example, silken-demo3Use a name that distinguishes this runtime from saved SILKEN workspaces.
resourcesFlexible, or Fixed: 2 CPU, 8 GB RAM, 0 GPUIncrease memory only for unusually large interactive products.
1
Launch and wait for Running.

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.

2
Open the active session.

Use the connect/open action on the session card. SILKEN appears directly under the authenticated CANFAR session URL.

3
Choose a SILKEN work session.

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.

Direct-launch boundary: this path opens the contributed runtime itself and does not use the public Arbutus BFF login. The MMP/Arbutus entry remains the path for cross-tool launch and token brokering; direct portal sessions still provide the core viewer, catalog, layer, job, and durable-workspace features.

CANFAR’s contributed-application contract and troubleshooting guidance are maintained in the official contributed applications guide.

Provider-neutral pattern

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.

Good fit

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.
Prefer a VM

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.
Provider-neutral pattern

The request lifecycle

1
Authenticate at the gateway.

Exchange user credentials or an identity assertion for a short-lived platform token. Keep secrets server-side.

2
Find or create an application session.

Reuse a healthy compatible session; otherwise request compute with the application image, resources, startup command, and environment.

3
Wait for an addressable service.

The scheduler mounts storage, starts the container, and returns a private connection URL after the HTTP service becomes ready.

4
Proxy browser traffic.

The gateway forwards API calls to the correct user session and adds a private service-to-service credential.

5
Persist before teardown.

State and results go to mounted durable storage. Session expiry removes compute capacity, not the saved work.

Key boundary: browser cookies identify a gateway session; they should not expose compute addresses, platform tokens, registry credentials, or backend secrets.
Provider-neutral pattern

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 classExpected interfaceCustom full web app
NotebookNotebook server and notebook-specific routingNo
Specialized viewerA named application such as an image or catalog viewerNo
Headless / batchA command that runs to completion without a browser interfaceFor background work
Generic application-session request
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.
Provider-neutral pattern

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.

1
Resolve the 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.

2
Label the immutable digest.

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.

3
Verify every published reference.

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.

Authentication boundary: a Harbor OIDC CLI secret is intended for Docker and Helm registry login and may not authorize REST artifact-label mutations. CI should use a dedicated least-privilege project robot with 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_USERNAME and HARBOR_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.

One-time GitHub secret setup (prompts for each value)
gh secret set HARBOR_LABEL_USERNAME --repo OWNER/REPOSITORY
gh secret set HARBOR_LABEL_PASSWORD --repo OWNER/REPOSITORY
Minimal global-label assignment using Harbor's REST API
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"])
CANFAR Harbor global-label mapping observed during validation (reference only)
{"1":"carta","2":"desktop","3":"desktop-app","4":"notebook","5":"headless","8":"contributed","11":"firefly"}

External references

Provider-neutral pattern

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.

Serialize

Capture intent

Save selections, views, queries, references, and settings—not an opaque process snapshot.

Commit

Write atomically

Write a temporary file, flush it, and rename it into place so readers see an old or new complete value.

Restore

Rebuild safely

Version the state format, tolerate missing resources, and migrate older layouts without deleting them first.

Atomic JSON persistence
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.

SILKEN implementation

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.

Always on

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/.

On demand

CANFAR runtime

Runs the private Python API close to mounted ARC data as a per-user Skaha contributed session.

Two supported entry paths

1
Standalone SILKEN.

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.

2
MMP-owned entry, the intended pattern.

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.

SILKEN implementation

Container and launch contract

The contributed image advertises its type, installs an executable startup script, and serves HTTP on CANFAR’s contributed-application port.

Dockerfile.canfar
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"]
Skaha form fields used by SILKEN
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.

SILKEN implementation

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.

/arc/home/<cadc-user>/.silken/ ├── workspace/ │ ├── state.json # current workspace │ └── sessions/ │ ├── index.json # names, timestamps, summaries │ └── session-<opaque-id>/state.json # complete UI workspace ├── jobs/<job-id>/ # science and silken.tool-run/v1 jobs ├── tools/ │ ├── definitions/<tool-id>.json # silken.tool/v1 definitions │ ├── sources/<source-id>/<commit>/ # managed immutable checkouts │ ├── inputs/ # durable query/table bindings │ ├── publish/ # editable COMET staging projects │ └── trust.json # revision-scoped confirmations ├── layers/<cadc-user>/ # generated image layers ├── saved_layers.json # saved-layer registry ├── resource-index/latest.json # active ARC index pointer ├── hats/ # user HATS registry and results ├── ../SILKEN/Exchanges/ # durable external-app handoffs └── ../SILKEN/Inbox/ # external-first return products

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.

1
Autosave.

The browser serializes versioned state after meaningful changes, with a short debounce.

2
Storage near the data.

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.

3
Resume.

A later runtime reads the session index and restores the selected SILKEN workspace. Pre-cutover application state is intentionally not imported.

SILKEN interoperability

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.

Capture

Whole workspace

Sky centre and FOV, ordered layers, queries, filters, selections, regions, styling, and provenance are written into a tool-neutral manifest.

Import

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.

Return

Merge safely

New images, tables, regions, and view context appear behind a badge, are preselected, and import as new layers or tabs without replacement.

/arc/home/<cadc-user>/SILKEN/Exchanges/<workspace>/<handoff>/ ├── manifest.json # silken.science-handoff/v1 authority ├── inputs/ # browser-only materializations ├── returns/ # products discovered after stable write └── native/ # optional application-native state

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.

Importing and opening are different operations. Importing never starts a CARTA, Firefly, or Neloura container: discovery and installation stay inside the single 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.
Durability boundary: a stopped or expired tool session can be recreated from the bundle. Tokens and transient connection URLs never enter the manifest or saved workspace.
SILKEN implementation

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.

Interactive

Session mode

Serial or threaded work in the user’s current contributed runtime. Best for smaller requests that benefit from immediate feedback.

Default

CANFAR headless

A separate headless run completes asynchronously. Manifests and results are exchanged through persistent ARC paths.

Distributed

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.

SILKEN operations

Deployment and replacement checks

  • The contributed image satisfies the provider-neutral registry-publication contract described in Architecture.
  • /skaha/startup.sh is executable and leaves the server in the foreground.
  • The runtime binds 0.0.0.0:5000 and 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 /tmp or /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.
Focused verification
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

Public BFF image
Dockerfile
Contributed runtime
Dockerfile.canfar
Runtime startup
scripts/silken-backend-startup
Launch, reuse, proxy, remote storage fallback
silken_bff.py
Direct Arc/Vault mount and persistence API
scripts/serve.py and workspace_sessions.py
Browser save and restore
viewer/index.html
Science handoff contract
science_handoffs.py

External references