Publish a pack
Upload bytes to Blob, verify them with @knolo/core, attest provenance, then release an immutable version.
01Browser: sign in and upload
Sign in with GitHub at /publish. The first login claims publishers.handle from the GitHub login. Select a .knolo (max 250 MB). The browser hashes it, asks POST /api/upload for a pathname locked to sha256/<digest>.knolo, and streams the file directly to a public Vercel Blob store. Hub never proxies the upload. Identical bytes reuse the existing digest.
02CLI tokens are not a GitHub session
Mint a kno_… token at /dashboard/tokens (GitHub session required only for that mint). Write APIs then accept Authorization: Bearer kno_… with scope publish. The word Bearer is required. A missing or malformed header returns 401 Sign in required — that does not mean Hub rejected the token in favor of GitHub. POST /api/v1/tokens stays session-only so a CLI key cannot mint more keys.
03knolo publish is still a stub
@knolo/cli 5.2.0 implements search, info, add, login, whoami, and logout. knolo publish and knolo yank still throw “Hub write APIs do not accept CLI tokens yet”. That message is stale. Hub already accepts Bearer tokens. Until the CLI wires publish, use /publish in the browser or the HTTP sequence on the CLI docs page. Do not wait for a GitHub session to “unlock” write APIs.
04Artifact URLs must be public
Verification GETs the Blob URL from the Hub job runner. A .private.blob.vercel-storage.com URL returns 403 and the job fails. POST /api/upload/complete rejects private URLs. PUT grants from POST /api/upload/token must land on a public store (hostname contains .public.blob.). Do not send the kno_ token to Blob.
05Verify
After the artifact row lands, Hub starts verifyPackWorkflow. Steps hash the blob against the pathname, inspect the container with @knolo/core 5.5.0, extract format / VQF-1 encoding / namespaces / docs, inspect agent registry metadata without executing it, secret-scan reconstructed logical text, and run sample queries. Poll GET /api/v1/publish/jobs/:id. A passed check is not a factual accuracy guarantee.
06Describe, attest, release
Bind publisher/slug@version with an SPDX license, readme, sources, intended use, and a rights attestation (POST /api/v1/publish/drafts). The describe step pre-fills the default license from /dashboard/settings. Release (POST /api/v1/publish/drafts/:id/release) lists the pack only if verification passed, the license is set, attestation is checked, and you own the handle. Yank is owner-only: the manifest becomes 410 and the Blob stays.