ci(secrets->kms): codex-channel-molecule fetches secrets from Infisical (migrate off Gitea Actions secrets) #15

Merged
agent-reviewer-cr2 merged 1 commits from ci/secrets-to-infisical-codex-channel-molecule into main 2026-06-26 04:33:23 +00:00
Owner

What

Migrate codex-channel-molecule off the repo-level Gitea Actions secret PYPI_TOKEN to the Infisical KMS-fetch pattern (proven #971 / #3274). This is a publish/CI-only repo with no prod-deploy — low risk.

Migrated secret

  • PYPI_TOKEN — consumed by .gitea/workflows/publish.yml (the publish job, secrets.PYPI_TOKEN). Now fetched at runtime from Infisical prod path /ci/pypi.

Not migrated (correctly skipped)

  • ci.yml consumes no secrets.
  • INFISICAL_CI_CLIENT_ID / INFISICAL_CI_CLIENT_SECRET / INFISICAL_CI_PROJECT_ID — bootstrap machine-identity secrets (used by the fetch step itself), skipped per policy.
  • GITEA_TOKEN / GITHUB_TOKEN — auto-injected, skipped.

How (same job as the consumer)

A new "Fetch PYPI_TOKEN from Infisical KMS" step is added to the publish job, before the Publish to PyPI step:

  1. universal-auth login (POST /api/v1/auth/universal-auth/login) using the INFISICAL_CI_* bootstrap secrets;
  2. read_secret()GET /api/v3/secrets/raw/PYPI_TOKEN?...&environment=prod&secretPath=%2Fci%2Fpypi with a null-safe JSON extractor;
  3. fail-closed on empty token / empty accessToken;
  4. ::add-mask:: the value, then export PYPI_TOKEN to $GITHUB_ENV.

The Publish to PyPI step now reads PYPI_TOKEN from the env — secrets.PYPI_TOKEN is no longer referenced anywhere.

Trusted-ref safety: this workflow only triggers on push: tags (vX.Y.Z), which fork PRs cannot reach, so consuming the INFISICAL_CI_* identity here carries no untrusted-fork exposure.

Validate-before-delete

The Gitea Actions secret PYPI_TOKEN is retained for now. It will be deleted only after this PR merges and a real publish run proves the Infisical fetch succeeds (green run). No Gitea secret is removed in this PR.

🤖 Generated with Claude Code

## What Migrate `codex-channel-molecule` off the repo-level **Gitea Actions secret `PYPI_TOKEN`** to the **Infisical KMS-fetch pattern** (proven #971 / #3274). This is a publish/CI-only repo with no prod-deploy — low risk. ### Migrated secret - **`PYPI_TOKEN`** — consumed by `.gitea/workflows/publish.yml` (the `publish` job, `secrets.PYPI_TOKEN`). Now fetched at runtime from Infisical prod path `/ci/pypi`. ### Not migrated (correctly skipped) - `ci.yml` consumes **no** secrets. - `INFISICAL_CI_CLIENT_ID` / `INFISICAL_CI_CLIENT_SECRET` / `INFISICAL_CI_PROJECT_ID` — bootstrap machine-identity secrets (used by the fetch step itself), skipped per policy. - `GITEA_TOKEN` / `GITHUB_TOKEN` — auto-injected, skipped. ## How (same job as the consumer) A new **"Fetch PYPI_TOKEN from Infisical KMS"** step is added to the `publish` job, before the `Publish to PyPI` step: 1. universal-auth login (`POST /api/v1/auth/universal-auth/login`) using the `INFISICAL_CI_*` bootstrap secrets; 2. `read_secret()` → `GET /api/v3/secrets/raw/PYPI_TOKEN?...&environment=prod&secretPath=%2Fci%2Fpypi` with a null-safe JSON extractor; 3. fail-closed on empty token / empty accessToken; 4. `::add-mask::` the value, then export `PYPI_TOKEN` to `$GITHUB_ENV`. The `Publish to PyPI` step now reads `PYPI_TOKEN` from the env — `secrets.PYPI_TOKEN` is no longer referenced anywhere. **Trusted-ref safety:** this workflow only triggers on `push: tags` (`vX.Y.Z`), which fork PRs cannot reach, so consuming the `INFISICAL_CI_*` identity here carries no untrusted-fork exposure. ## Validate-before-delete The Gitea Actions secret **`PYPI_TOKEN` is retained for now**. It will be deleted only **after** this PR merges and a real publish run proves the Infisical fetch succeeds (green run). No Gitea secret is removed in this PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hongming added 1 commit 2026-06-26 04:25:22 +00:00
ci(secrets->kms): codex-channel-molecule fetches PYPI_TOKEN from Infisical
CI / test (3.11) (pull_request) Successful in 56s
CI / test (3.12) (pull_request) Successful in 1m3s
ac73c6bf24
Migrate the publish job off the repo-level Gitea Actions secret PYPI_TOKEN
to the Infisical KMS-fetch pattern (proven #971/#3274).

In the same `publish` job as the consumer, add a "Fetch PYPI_TOKEN from
Infisical KMS" step that:
  - logs in via universal-auth using the INFISICAL_CI_* bootstrap secrets
  - reads PYPI_TOKEN from prod /ci/pypi with a null-safe extractor
  - fails closed on an empty value
  - masks it (::add-mask::) and exports to $GITHUB_ENV
The "Publish to PyPI" step now reads PYPI_TOKEN from the env (no more
secrets.PYPI_TOKEN).

Trusted-ref: this workflow only triggers on push:tags (vX.Y.Z), which
fork PRs cannot reach, so consuming the INFISICAL_CI_* identity is safe.

Validate-before-delete: the Gitea Actions PYPI_TOKEN secret is retained
until a real green publish run proves the fetch, then it is deleted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
agent-reviewer-cr2 approved these changes 2026-06-26 04:30:07 +00:00
agent-reviewer-cr2 left a comment
Member

APPROVED #15 @ac73c6bf24bae0b20f13d92a6d29d3eeef153c8a. Reviewed Wave A KMS migration: workflow is tag-push only (no pull_request/pull_request_target/fork exposure), PYPI_TOKEN extractor is string-only/null-safe (json null/missing/non-string -> empty), [ -z ] fails closed, ::add-mask:: occurs before $GITHUB_ENV export, Gitea PYPI_TOKEN is retained for validate-before-delete, and diff is scoped to publish.yml. YAML parses. Note: I saw no status contexts on this PR head in the statuses API, so merge should still wait for the expected BP/CI signal if branch protection requires one.

APPROVED #15 @ac73c6bf24bae0b20f13d92a6d29d3eeef153c8a. Reviewed Wave A KMS migration: workflow is tag-push only (no pull_request/pull_request_target/fork exposure), PYPI_TOKEN extractor is string-only/null-safe (json null/missing/non-string -> empty), [ -z ] fails closed, ::add-mask:: occurs before $GITHUB_ENV export, Gitea PYPI_TOKEN is retained for validate-before-delete, and diff is scoped to publish.yml. YAML parses. Note: I saw no status contexts on this PR head in the statuses API, so merge should still wait for the expected BP/CI signal if branch protection requires one.
agent-researcher approved these changes 2026-06-26 04:30:57 +00:00
agent-researcher left a comment
Member

APPROVED — reviewed head ac73c6bf24.

Scope: Wave A Gitea→Infisical migration for PYPI_TOKEN in .gitea/workflows/publish.yml.

5-axis summary: correctness/security/robustness/perf/readability all clean for this low-risk publish-only path. The workflow is tag-push only, with no pull_request or pull_request_target trigger, so I do not see an untrusted fork path to the INFISICAL_CI identity. The accessToken and PYPI_TOKEN extractors use the null-safe/type-safe idiom (isinstance(v, str) else ""), followed by [ -z ] fail-closed guards. ::add-mask:: is emitted before exporting to $GITHUB_ENV, logging is length-only, and the PR does not delete the existing Gitea PYPI_TOKEN secret. Full-paginated BP-required statuses are green (CI / test (3.11) and CI / test (3.12)). No unrelated edits found.

APPROVED — reviewed head ac73c6bf24bae0b20f13d92a6d29d3eeef153c8a. Scope: Wave A Gitea→Infisical migration for PYPI_TOKEN in `.gitea/workflows/publish.yml`. 5-axis summary: correctness/security/robustness/perf/readability all clean for this low-risk publish-only path. The workflow is tag-push only, with no pull_request or pull_request_target trigger, so I do not see an untrusted fork path to the INFISICAL_CI identity. The accessToken and PYPI_TOKEN extractors use the null-safe/type-safe idiom (`isinstance(v, str) else ""`), followed by `[ -z ]` fail-closed guards. `::add-mask::` is emitted before exporting to `$GITHUB_ENV`, logging is length-only, and the PR does not delete the existing Gitea PYPI_TOKEN secret. Full-paginated BP-required statuses are green (`CI / test (3.11)` and `CI / test (3.12)`). No unrelated edits found.
agent-reviewer-cr2 merged commit 8c04a1f708 into main 2026-06-26 04:33:23 +00:00
Sign in to join this conversation.
No Label
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/codex-channel-molecule#15