CI/CD Secrets Configuration

CI/CD Secrets Configuration

Version: 3.0 Last Updated: 2026-07-15 Target Audience: Repository maintainers and administrators

AIWG's Gitea CI/CD workflows use vault for repository-managed secrets. Gitea Actions stores only the vault bootstrap pair:

Tracker secretPurpose
`VAULT_CI_ROLE_ID`AppRole role ID for the `ci-aiwg` reader.
`VAULT_CI_SECRET_ID`AppRole secret ID for the `ci-aiwg` reader.

Do not recreate legacy Gitea secrets such as `NPM_TOKEN`, `GH_ACCESS_TOKEN`, `AIWG_IO_DISPATCH_TOKEN`, or `DOCSITE_DEPLOY_KEY`. Those values live in vault and are fetched at runtime with `../../ci/vault-fetch.sh`.

`secrets.GITHUB_TOKEN` is not part of this migration. It is a per-run token issued by the CI system and is still used by PR-comment workflows.

Vault Fetch Specs

WorkflowSpecExported value
`.gitea/workflows/npm-publish.yml``ci/vault-fetch.npm-publish.spec``NODE_AUTH_TOKEN`
`.gitea/workflows/gitea-release.yml``ci/vault-fetch.gitea-release.spec``GITEA_TOKEN`
`.gitea/workflows/upload-release-sigs.yml``ci/vault-fetch.upload-release-sigs.spec``GITEA_TOKEN`
`.gitea/workflows/github-mirror.yml``ci/vault-fetch.github-mirror.spec``GH_TOKEN`
`.gitea/workflows/notify-site.yml``ci/vault-fetch.notify-site.spec``AIWG_IO_DISPATCH_TOKEN`
`.gitea/workflows/docsite-deploy.yml``ci/vault-fetch.docsite-deploy.spec``DOCSITE_DEPLOY_KEY_FILE`

The specs contain only `_VAULT_PATH` and `_VAULT_FIELD` placeholders. Concrete vault paths, metadata paths, hostnames, and fields are stored as private Gitea variables or in the private operations catalog.

Validate specs without reading live secrets:

for f in ci/vault-fetch.*.spec; do
  bash ci/vault-fetch.sh --spec "$f" --dry-run
done

Run the local consistency gate:

npm run lint:vault-migration

Classification

NameClassDestination
`VAULT_CI_ROLE_ID``BOOTSTRAP`Gitea Actions secret
`VAULT_CI_SECRET_ID``BOOTSTRAP`Gitea Actions secret
`GITHUB_TOKEN`CI-issued tokenNo storage; issued per run
`GT_NPM_TOKEN_VAULT_PATH`, `GT_NPM_TOKEN_VAULT_FIELD``ROUTE`Gitea Actions variables
`GT_RELEASE_TOKEN_VAULT_PATH`, `GT_RELEASE_TOKEN_VAULT_FIELD``ROUTE`Gitea Actions variables
`GH_MIRROR_TOKEN_VAULT_PATH`, `GH_MIRROR_TOKEN_VAULT_FIELD``ROUTE`Gitea Actions variables
`AIWG_IO_DISPATCH_TOKEN_VAULT_PATH`, `AIWG_IO_DISPATCH_TOKEN_VAULT_FIELD``ROUTE`Gitea Actions variables
`DOCSITE_DEPLOY_KEY_VAULT_PATH`, `DOCSITE_DEPLOY_KEY_VAULT_FIELD``ROUTE`Gitea Actions variables
`RELEASE_SIGNING_KEY_VAULT_PATH`, `RELEASE_SIGNING_KEY_VAULT_FIELD``ROUTE`Gitea Actions variables
`RELEASE_SIGNING_PASSPHRASE_VAULT_PATH`, `RELEASE_SIGNING_PASSPHRASE_VAULT_FIELD``ROUTE`Gitea Actions variables
`VAULT_ADDR``ROUTE`Gitea Actions variable
`DOCSITE_DEPLOY_HOST`, `DOCSITE_DEPLOY_PORT`, `DOCSITE_DEPLOY_USER`, `DOCSITE_DEPLOY_PATH``CONFIG`Gitea Actions variables

The machine-readable variable manifest is `../../ci/vault-migration-plan.json`.

Provisioning

Use the private operations catalog to create the scoped policy and AppRole. Keep the concrete policy file outside this repository, then pass it to:

npm run provision:vault-approle -- --policy-file /path/to/private-policy.hcl
VAULT_ADMIN_TOKEN=<admin-token> npm run provision:vault-approle -- \
  --policy-file /path/to/private-policy.hcl \
  --apply

To induct or rotate values from an approved local medium, prepare one file per route ID:

gitea-npm-token.value
gitea-release-token.value
github-mirror-token.value
aiwg-io-dispatch-token.value
docsite-deploy-key.value
release-signing-key.value
release-signing-passphrase.value

Preview the vault writes without printing paths:

npm run provision:vault-migration -- \
  --routing-env /path/to/private-routing.env \
  --values-dir /path/to/approved-value-files

Apply only after confirming the private routing env and value files:

npm run provision:vault-migration -- \
  --routing-env /path/to/private-routing.env \
  --values-dir /path/to/approved-value-files \
  --apply

Validate and apply the Gitea handoff without printing values:

npm run configure:gitea-vault -- \
  --bootstrap-env ~/.config/vault/handoff/aiwg-ci.env \
  --vars-env /path/to/private-routing-and-deploy.env

npm run configure:gitea-vault -- \
  --bootstrap-env ~/.config/vault/handoff/aiwg-ci.env \
  --vars-env /path/to/private-routing-and-deploy.env \
  --apply

Docsite Deployment Config

The `Docsite Deploy` workflow publishes the AIWG documentation tenant over SSH. The private key is fetched from vault. Target connection details are Gitea Actions variables and should not be hardcoded in workflow files.

`GT_ACCESS_TOKEN` is not used by AIWG's current docsite workflows. The publisher is installed from npm as `@pagenary/publisher`; do not add a clone token back to the docsite workflows unless the publisher source model changes again.

Troubleshooting

Vault Bootstrap Missing

If `VAULT_CI_ROLE_ID` or `VAULT_CI_SECRET_ID` is absent, secret-bearing Gitea jobs skip instead of attempting a partial publish. Add or rotate the AppRole bootstrap pair in Gitea Actions secrets.

Fetch Fails with 403

The `ci-aiwg` AppRole is missing the required path policy or is trying to read the wrong leaf. Compare the workflow spec placeholder names with the private vault routing env and policy.

Gitea Registry Publish Fails

Check the private routing entry, token scope, and token freshness. The value must remain vault-only.