Token scope is now bound to package maturity, gated on netkingdom's own maturity: - maturity-build -> gitea-wide, maturity-test -> org-wide, maturity-prod -> repo-scoped (scope narrows as stakes rise; broad tokens only for low-stakes build artifacts) - the graduated table is DORMANT until netkingdom reaches production grade; until then every lane clamps to repo-scope, injected as NPM_AUTH_TOKEN (fail-safe) - token env-var name signals blast radius: NPM_AUTH_TOKEN (repo default), NPM_AUTH_COULOMB_TOKEN (org), NPM_AUTH_GITEA_TOKEN (gitea), NPM_AUTH_WHYNOT_TOKEN (npm scope, defined but unused), NPM_AUTH_WHYNOTDESIGN (explicit repo) netkingdom is at maturity-build today, so whynot-design resolves to repo-scope / NPM_AUTH_TOKEN. Flip netkingdom_maturity to maturity-prod to activate graduation. - policies/netkingdom-publication-scope.yaml: the policy data + gate - publication_policy.py: load + resolve (clamp/active, env naming, override) - exec delivery injects under the resolved env-var name (was fixed SE_NPM_TOKEN) - catalog lane carries delivery_config.npm.maturity - new CLI: `secrets-engine policy publication <lane>` - docs/publication-scope-policy.md; tests for clamp, graduation, naming, override Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
3 KiB
YAML
74 lines
3 KiB
YAML
# 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"
|
|
# Package maturity tag. Under the netkingdom publication-scope policy this
|
|
# would map to a publication scope (build->gitea, test->org, prod->repo) once
|
|
# netkingdom is production grade. netkingdom is at maturity-build today, so the
|
|
# policy is dormant and this lane clamps to repo-scope, injected as
|
|
# NPM_AUTH_TOKEN. Set `token_env` to override the resolved name.
|
|
maturity: maturity-build
|
|
# token_env: NPM_AUTH_WHYNOTDESIGN # explicit per-repo form (optional)
|
|
|
|
# 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"
|