Static file store for Verifiable Credential artifacts published by eAPI’s credential service, served publicly via GitHub Pages. Wallets, issuers, and verifiers resolve schemas, JSON-LD contexts, VCT definitions, and revocation status lists from URLs in this repo.
Once a file is published here, it must never be edited, moved, renamed, or deleted (the one exception is status/ files — see below).
Every file’s GitHub Pages URL (https://{GITHUB_PAGES_DOMAIN}/... — domain root, custom domain, no /vc-artifact-registry segment) is permanently embedded inside credentials already issued to holders’ wallets — in the credential’s credentialSchema, @context, VCT id/schema/jsonLdContext, and bitStringStatusListURL fields. A wallet cannot be updated after issuance. Moving or changing a published file breaks every credential that references it, with no way to fix it after the fact.
If a schema or artifact needs to change, publish a new file (new version, new timestamp suffix) — never overwrite an existing one.
vc-artifact-registry/
├── core/
│ └── vocab/
│ └── vocab.jsonld
│ # ONE shared JSON-LD vocabulary for the whole repo, not per-environment,
│ # not per-LOB. Referenced by fragment from context files, e.g.:
│ # https://{GITHUB_PAGES_DOMAIN}/core/vocab/vocab.jsonld#country
│ # `core/` is the container for ANY environment-agnostic content —
│ # not just vocab. Rule: a top-level folder in this repo is either an
│ # environment name, or `core`. Nothing else goes at the root.
│
├── dev/ ← environment (from GITHUB_PATH_ENVIRONMENT)
│ └── orga-adarsh-otp-tenant1/ ← lobEcoSystemName (tenant-chosen at LOB registration)
│ └── insurance-lob/ ← lobDisplayName
│ │
│ ├── schema/
│ │ └── insurance-policy-1.0.json
│ │ # BASE schema. One per schema+version. No timestamp — this is the
│ │ # canonical schema definition (attributes, governance URL). Created
│ │ # once when a schema is first published; re-published only on a new
│ │ # schemaVersion.
│ │
│ ├── context/
│ │ └── insurance-policy-1778856680321-1.0.jsonld
│ │ # JSON-LD @context. Maps each schema attribute name to a semantic
│ │ # IRI/term (uses core/vocab/vocab.jsonld + external vocabularies). This is
│ │ # what a JSON-LD credential's "@context" array points to.
│ │
│ ├── w3cSchema/
│ │ └── insurance-policy-1778856680321-1.0.json
│ │ # W3C JSON Schema (draft-07 style). Defines the actual JSON shape/
│ │ # validation rules for the credentialSubject. This is what a verifier
│ │ # validates a received credential's payload against.
│ │
│ ├── vct/
│ │ └── insurance-policy-1778856618754-1.0.json
│ │ # "Verifiable Credential Type Definition" — NOT the credential itself,
│ │ # and not a schema. It's a small manifest/pointer document that ties
│ │ # everything else together: it holds
│ │ # - id: this file's own GitHub Pages URL
│ │ # - schema: {$ref to the base schema AND the w3cSchema file above}
│ │ # - jsonLdContext: pointer to the context/ file above
│ │ # - propertyBindings: which schema field maps to which JSON-LD term
│ │ # - bitStringStatusListURL: pointer to the status/ file below
│ │ # Issuers/verifiers fetch the VCT first, then follow its pointers to
│ │ # the schema/context/status files. Think of it as the "index card"
│ │ # for one issued credential type — one per cred-def, not per schema.
│ │
│ └── status/
│ └── InsurancePolicy-revocation-1778856680321.json
│ # BitString Status List credential — a single growing bitstring where
│ # bit N = revoked/suspended flag for the Nth credential issued under
│ # this cred-def. A verifier fetches this and checks one bit to know if
│ # a specific credential has been revoked. One per cred-def (only
│ # created if supportRevocation is enabled). THIS is the one file type
│ # that legitimately gets updated in place over time (bits flip as
│ # credentials are revoked) — it is not a versioned snapshot like the
│ # other four artifact types.
│
├── qa/ └── {lobEcoSystemName}/{lobDisplayName}/schema|context|w3cSchema|vct|status/...
├── prod/ └── {lobEcoSystemName}/{lobDisplayName}/schema|context|w3cSchema|vct|status/...
├── sandbox/ └── {lobEcoSystemName}/{lobDisplayName}/schema|context|w3cSchema|vct|status/...
├── stg/ └── {lobEcoSystemName}/{lobDisplayName}/schema|context|w3cSchema|vct|status/...
└── cs-prd/ └── {lobEcoSystemName}/{lobDisplayName}/schema|context|w3cSchema|vct|status/...
| Folder | Describes | Created | Mutability |
|---|---|---|---|
schema/ |
Data shape, loosely typed | Once per schema version | Immutable |
w3cSchema/ |
Data shape, W3C-strict (what a verifier validates payloads against) | Once per JSON-LD schema publish | Immutable |
context/ |
Meaning — JSON-LD term mappings | Once per JSON-LD schema publish | Immutable |
vct/ |
Manifest — pointers to schema + w3cSchema + context + status, plus property bindings | Once per credential definition | Immutable |
status/ |
Live revocation state for one cred-def | Once per cred-def (only if revocation enabled) | Mutable — bits flip as credentials are revoked |
The top-level folder is the deployment environment that published the artifact. It comes from the credential service’s GITHUB_PATH_ENVIRONMENT env var — by convention one of dev, qa, prod, sandbox, stg, cs-prd, though this is not enforced by an enum in code; whatever string is configured for a given deployment is what gets written.
core/core/ holds anything environment-agnostic — content that’s identical across dev/qa/prod and shouldn’t be duplicated per environment. Today that’s just core/vocab/vocab.jsonld, a shared JSON-LD vocabulary referenced by term fragments (e.g. vocab.jsonld#country, #locality, #religion) from generated @context files — but any future global asset belongs here too, not at the repo root.
core/vocab/vocab.jsonld is a byte-identical duplicate of northern-block/test-jsonld/vocab.jsonld, carried over with the same term fragments so that credentials issued against the old repo and the new repo resolve to the same semantic terms.
Below the environment, structure is unchanged from the legacy northern-block layout: {lobEcoSystemName}/{lobDisplayName}/{artifactType}/{fileName}. lobEcoSystemName and lobDisplayName are tenant-supplied at LOB registration; artifactType is one of the five described above.
There is no build step here — this repo is the GitHub Pages content. Files land under https://{GITHUB_PAGES_DOMAIN}/<path> (domain root, no /vc-artifact-registry segment) as soon as they’re merged to main.
Requires a CNAME file + custom domain configured in this repo’s Settings → Pages for GITHUB_PAGES_DOMAIN to actually resolve — not yet set up as of this writing. Until that’s done, generated URLs will not be reachable; do not let credential publish real artifacts against this repo before it is.
The credential service (orbit-enterpriseapi-client/apps/credential) is the only writer, via GithubService (orbit-enterpriseapi-internal/packages/shared-enum/src/github). Path construction lives in JSONLdContextUtils (apps/credential/src/{v1,v2}/schema/jsonld-context.utils.ts).
Relevant config in credential’s .env:
GITHUB_OWNER=<owner>
GITHUB_REPO=vc-artifact-registry
GITHUB_BRANCH=main
GITHUB_TOKEN=<token>
GITHUB_PATH_ENVIRONMENT=<dev|qa|prod|sandbox|stg|cs-prd> # required — app fails to start if unset