facet publish reads the built .facet from dist/, verifies it end-to-end via the archive-verification operation defined by this specification (see Facet Archive), and uploads the verified bytes to the registry. Building and publishing are distinct steps — facet build is the sole producer of the archive, and publish never constructs it on its normal path.
This page specifies what publishing means — the verification obligations, the registry’s behavior, and the decision semantics when the built artifact is missing or has drifted from source. Command usage, flags, and the interactive prompt flow are documented at facet publish.
Authentication
Publishing is an authenticated operation. The CLI sends anAuthorization: Bearer <token> header on the publish request, where the token is a personal access token (PAT) minted in the web UI. If no credential can be resolved, facet publish MUST fail before any verification or registry round-trip. Credential management — where tokens live and how they are resolved — is CLI behavior; see facet login.
Errors returned by the registry MUST be rendered verbatim — implementations show the registry’s own message and suggested fix rather than maintaining their own copy of what each error code means. A duplicate-version publish, for example, surfaces the registry’s “version already exists” guidance directly.
What the author uploads
The CLI uploads the complete built.facet archive — the same self-contained two-layer artifact facet build produced. The outer tar contains the build-manifest.json (recording the integrity hash and the complete per-entry files hash map) and the gzipped inner archive (carrying the embedded facet.json, every declared asset, and every declared supplementary file). No part of the archive is re-derived at upload time: the bytes on disk are the bytes on the wire.
The name and version used to address the upload come from the verified artifact’s embedded manifest, not from a separate parse of the source-tree facet.json. This matters when the user explicitly chooses to ship a drifted artifact under its own embedded identity (see identity drift).
The manifest’s private declaration is part of that embedded manifest, so it travels with the upload like any other manifest content — there is no separate publish flag for privacy. The registry reads the author’s privacy intent from the embedded facet.json. Registry-side authorization and visibility enforcement are outside the CLI/protocol surface described here.
What the registry does
-
Verify the upload. The registry runs the same archive-verification operation
facet publishran locally: dispatch on the archivefacetVersion(accepting both the current0.2and legacy0.1during the compatibility window), parse the outer container, decompress the inner archive (within the registry’s size policy), verify the integrity hash, verify each per-entry hash, validate the embedded manifest, and apply the artifact content rules — including the expanded supplementary-file membership. A verification failure rejects the publish. The registry is a separate implementation of this specification and adopts the same relaxed rules. -
Store the artifact. The verified bytes are stored under
(name, version). The registry records both the canonical fingerprint (content_integrity) and the transport hash (content_hash). Consumers verify both at different stages (see Integrity Model).
Review queue
A first-time publish MAY be accepted into a moderation queue rather than published immediately — for example when the requested name is reserved, or the account has exceeded its tier’s publish budget. This is a success outcome: implementations MUST report that the submission was queued for review and render the registry’s guidance. The version becomes available once an admin approves it.Immutability
Once a facet version is published, the registry MUST NOT allow re-publishing the same name and version with different content. A version, once published, is immutable. Becauseprivate is manifest content embedded in the artifact, changing a facet’s privacy after a version is published requires the same version bump as any other content change. Re-publishing the same (name, version) with a flipped private value collides with immutability and is rejected; publish the visibility change under a new version.
When the built artifact is missing
Whendist/ is empty (or doesn’t exist), there is nothing for publish to ship, and the registry MUST NOT be contacted:
- Interactive contexts MAY offer to build the current source and, on acceptance, verify and upload the freshly built artifact. On decline, the operation fails.
- Non-interactive contexts (CI, piped stdin) MUST NOT prompt and MUST fail with guidance to run
facet buildfirst.
facet publish.
When the built artifact has drifted from source
Whendist/ contains a .facet but its embedded manifest disagrees with the current source-tree facet.json, implementations MUST distinguish two drift classes:
Content drift — same name and version, different manifest content (the user edited description, private, an asset descriptor, or similar without rebuilding). Either resolution uploads to the same (name, version) address; the registry has no view into the user’s local edits. Interactive contexts MAY offer to rebuild and publish the new artifact, or to publish the existing artifact unchanged. Editing private is content drift like any other manifest edit — publishing the existing artifact ships its embedded privacy declaration unchanged, while rebuilding embeds the new value.
Identity drift — different name or different version (the most common case: the user bumped version to 0.2.0 but dist/ still has the 0.1.0 artifact). Uploads always address the artifact’s embedded identity, so publishing the existing artifact ships it under its own (name, version) — and collides with immutability if that identity is already published. Interactive contexts MAY offer to rebuild from the current source, publish the existing artifact as-is, or cancel without contacting the registry.
Non-interactive contexts MUST NOT prompt. Both drift classes fall back to the same default: emit a warning summarising the drift, then upload the existing artifact unchanged (warn-and-ship).
The prompt choreography for both drift classes is documented at facet publish.
Build vs. publish
Neither step mutates the manifest. An invalid input fails the respective step — publish fails with a verification error and never contacts the registry.
Not in publish
- Server references —
serversentries in the manifest are stored as declared but not resolved or published. - Lockfile generation — the lockfile is an install-time artifact, not a publish-time artifact.