Publishing a namespace
Publish from CI with a publisher key, a namespace-scoped credential that can call the publish endpoint and nothing else. The payload is theCatalogDocument produced by catalog.toDocument():
scripts/publish-catalog.ts
expectedVersion for compare-and-set publishes. The same publish is available from the application page in the Dashboard, and both paths call the same server function.
Versions are monotonic
Versions increase monotonically per namespace, and out-of-order publishes are rejected. A rollback deploy that republishes an older document cannot un-publish newer keys: the registry refuses the stale version, and the newer contract stands. Roles and grants referencing recently-added keys never dangle because a deploy went backwards.Additions need no coordination
Adding a permission to your catalog requires no registry-side ceremony beyond the publish itself. Forward-inclusive wildcards absorb new keys the moment they are published, so a role grantingdocs.files.* covers a docs.files.archive permission added a year later, with no role edit and no re-grant.
Removals are tombstones
Removal is never deletion. A key that disappears from a published document is tombstoned: it stops matching checks immediately, but it remains visible in the registry as deprecated, with its history intact. Grant rows referencing it are not silently rewritten. The drift report closes the loop: it names every role and every grant still referencing keys no longer published by any application. You review and migrate them deliberately. The registry surfaces the debt; it does not pay it down behind your back.Typed consumption across the boundary
A consuming application can hold typed keys for a namespace it does not own. Export the published document and run codegen against it:docs.files.* with zoom.host is compile-checked in the consuming codebase, exactly as local keys are.
Commit that document and declare the slice you interface with as an import. The consuming catalog then treats those keys as its own for typing, verification, and grants, while toDocument() keeps publishing only what you actually own.
What each application consumes
The drift report above reads roles and grants. It cannot see code, so an application whose catalog still imports a tombstoned key looks clean until its next deploy. Publishing the import manifest closes that gap. It is a separate artifact from the catalog on purpose: what you announce is vocabulary others may write grants against, what you consume is a dependency only others can warn you about.publishImports writes a versioned manifest to your own Application’s storage. It posts nothing to the registry, and needs no network. Alfiz Cloud reads it back over the relay like any other provider operation. The op is optional: it needs a driver implementing putImports / getImports (the AlfizImports model in the Prisma fragment), and capabilities().imports reports whether yours has it.