# whynot-design npm publish token — the MVP pilot lane. # This file is NON-SECRET. It describes where the token lives in OpenBao and how # it may be consumed. The token VALUE never appears here. # # Terminology (Gitea is overloaded — we use the most explicit words): # org = coulomb the Gitea organisation # repo = whynot-design the Gitea repository / product (NOT an org, NOT a scope) # npm package = @whynot/design published to the coulomb Gitea npm registry # "@whynot" is the npm *scope*; it is neither the org nor the repo name. id: whynot-design-npm-publish org: coulomb repo: whynot-design stage: prod description: >- npm automation token used to publish the @whynot/design package from the coulomb/whynot-design repo to the coulomb Gitea npm registry. Delivered to `npm publish` via an exec-time temporary npm config; never printed or exported into the parent shell. # OpenBao KV v2 location of the secret material (org/repo-scoped path). mount: secret path: coulomb/whynot-design/npm/publish # Field(s) inside the KV entry. The publish token is stored under this key. fields: - npm_token # Who may consume this lane and the identity claim that binds them. consumers: - name: whynot-design-ci auth: approle # bound OpenBao auth method claim: "repo:coulomb/whynot-design" purpose: "publish @whynot/design to the coulomb Gitea npm registry from CI" # How the value may leave OpenBao. npm-config = temp .npmrc for the child only. delivery_modes: - npm-config - read-check # npm-specific delivery target. The registry/scope live here as catalog DATA so # the engine never hardcodes a registry. Matches coulomb/whynot-design/.npmrc. delivery_config: npm: registry: "https://gitea.coulomb.social/api/packages/coulomb/npm/" scope: "@whynot" package: "@whynot/design" # Privileged actions on this lane require an approved decision/CCR. approval: model: decision decision_ref: "whynot-design-npm-publish" # State Hub decision/CCR id or slug notes: "Production lane: apply requires an approved decision." # Verification expectations (no value is ever printed). verification: positive: "approved consumer token can read the lane field" negative: "an unrelated token is denied read on the lane path" rotation: expectation: "rotate on compromise or every 90 days" ttl: "90d" deactivation: expectation: "revoke approle + delete KV metadata; record evidence" audit: evidence: "decision id, actor, path, timestamp, result — no secret value"