Skip to content

ci: wire named_keys_v1 as a docker.yml workflow input (TC-1777) - #447

Merged
samgbafa merged 4 commits into
mainfrom
amos/tc1777-named-keys-input
Oct 26, 2026
Merged

samgbafa merged 4 commits into
mainfrom
amos/tc1777-named-keys-input

Conversation

@samgbafa

@samgbafa samgbafa commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Details: TC-1777

What

Wires the named-keys release gate as a docker.yml workflow_dispatch input, so the Tue 10-27 flip is a normal dispatch and never a hand phala deploy -e (which would replace the sealed env and drop DSTACK_AUTHORIZED_KEYS).

  • .github/workflows/docker.yml
    • new input named_keys_v1 (boolean, default false, required: false, so every existing dispatch line stays valid unchanged);
    • PHALA_ENV_NAMED_KEYS_V1: ${{ inputs.named_keys_v1 }} on the Deploy to Phala Cloud step, added to required_vars, written as printf 'NAMED_KEYS_V1=%s\n' … right after SQL_IDENTITY_FENCE;
    • the value must be exactly true or false (constant error, before .phala-prod.env is written);
    • n0_template_hash 8df7e0f2… → c9bcbea9dac90fc2b74d8439146596ba802796a211d1b6d65aeda2286d7ed028.
    • The DSTACK_AUTHORIZED_KEYS line and the phala deploy … -e .phala-prod.env call are untouched.
  • docker-compose.dstack-postgres.yaml (tinycloud service)
    • TINYCLOUD_ENCRYPTION_NETWORK__NAMED_KEYS_V1: "${NAMED_KEYS_V1:-false}"
    • TINYCLOUD_ENCRYPTION_NETWORK__DELETION_LEDGER_PATH: /var/lib/tinycloud/ledger/deletions.jsonl
    • volume deletion-ledger:/var/lib/tinycloud/ledger + top-level deletion-ledger:
  • scripts/ci/fixtures/tc959-n0-compose.yaml: byte copy of the compose (it always is; the test harness hashes it against n0_template_hash).
  • docs/releasing.md: the pinned template hash and the raw compose hash it states (old values kept in the history chain). The historical table in docs/runbooks/tc-959-n0-log-shipping.md is left as recorded.
  • scripts/ci/test-deploy-recovery.py: additive only (see Tests).

Findings that differ from the spec

  • No allowed-names list or phala-env-sync/ directory exists in the repo. sync.mjs is a heredoc inside docker.yml's Prepare allowed_envs synchronization step and has no hard-coded whitelist: it reads allowed_envs from the CVM's compose, requires every allowed name to be present in .phala-prod.env (--check), and PATCHes any name in the file but not yet allowed. NAMED_KEYS_V1 therefore needs no sync.mjs change. The first dispatch carrying it adds the name through that existing PATCH path, as SQL_IDENTITY_FENCE/NODE_STATS_READ_TOKEN did. There was nothing to update in sync.mjs's tests; the deploy-step harness (test-deploy-recovery.py) is its test surface.
  • encryption: seeded deletable keys under apps/, depth rule, state guards #436 and encryption: owner-signed key and prefix delete with a deletion ledger #438 touch none of these files. Neither changes docker.yml, any compose file or the fixture. encryption: owner-signed key and prefix delete with a deletion ledger #438 (tc1777/n3b-key-delete, 4644aaf) adds the config key encryption_network.deletion_ledger_path (documented env TINYCLOUD_ENCRYPTION_NETWORK__DELETION_LEDGER_PATH) and refuses to start with named_keys_v1=true and no ledger path, and its Dockerfile creates /var/lib/tinycloud/ledger owned 1000:1000, mode 700, which is what makes a named volume mounted at that path writable by the tinycloud user on first mount. Nothing is duplicated; this PR is the deploy-side counterpart. encryption: seeded deletable keys under apps/, depth rule, state guards #436 (6a94e39) only adds the key backend/routes.
  • Not changed (spec said no other changes): the Preflight sealed runtime configuration step does not pass NAMED_KEYS_V1/ledger path to --validate-config, so that preflight does not exercise the flipped configuration.

Default false = behaviour unchanged

For named_keys_v1=false (every existing dispatch line, which never mention it):

  • the sealed file gains one line, NAMED_KEYS_V1=false; every other line and DSTACK_AUTHORIZED_KEYS are unchanged;
  • the node gets TINYCLOUD_ENCRYPTION_NETWORK__NAMED_KEYS_V1="false", the same as the gate's default off. The ledger path env/volume are inert for the 1.23.0/1.20.6 images (EncryptionNetworkConfig has no deny_unknown_fields).
  • Compose/CVM-side: the new env names and volume change the compose hash once, on the first deploy after this merges, like any compose edit.

Proof: docker compose --env-file … config on the real compose renders NAMED_KEYS_V1: "false" with no NAMED_KEYS_V1 in the env file, "false" with NAMED_KEYS_V1=false, "true" with NAMED_KEYS_V1=true, with the ledger path and deletion-ledger volume (target /var/lib/tinycloud/ledger) in all three.

Flip and rollback (dispatch, never -e)

Flip (use the same digest/labels as the release being run; shown for 1.24.0):

gh workflow run docker.yml -R TinyCloudLabs/tinycloud-node --ref main \
  -f deploy_phala=true \
  -f authorize_quota_values=true \
  -f image_version=1.24.0 \
  -f deploy_image_digest=sha256:<release-dstack-digest> \
  -f rollback_image_version=1.24.0 \
  -f rollback_image_revision=<release-commit-sha> \
  -f sql_identity_fence=false \
  -f named_keys_v1=true

Rollback of the flag only: the identical dispatch with -f named_keys_v1=false (same digest and rollback inputs). Omitting the input has the same effect.

Tests (run locally on this head)

  • python3 scripts/ci/test-deploy-recovery.py: Ran 27 tests, OK (25 existing + 2 new).
    • New: test_named_keys_gate_is_sealed_as_a_literal_flag_beside_the_ssh_keys (true/false sealed once, DSTACK_AUTHORIZED_KEYS kept once, sealed value equals the input) and test_named_keys_gate_other_than_true_or_false_is_refused_before_the_file ("", TRUE, 1, yes, maybe, true refused before the sealed file and before any CVM mutation).
    • Existing test lines edited: none (additive: one stub line in the fake node CLI, one env line in run_deploy, the two tests).
  • actionlint .github/workflows/docker.yml: the same 2 shellcheck findings as on origin/main (SC2016 info and SC2034 warning, only line numbers shifted); nothing new.
  • Template hash by the workflow's own method (digest normalized to 64 zeros, SHA-256): the old compose reproduces 8df7e0f2…; the new compose gives c9bcbea9… (raw 298ea356adf8d5e562557ab18bd3f5d8cdb816de82b1eaf6e6e50bf888e22765). The N0 path of the deploy harness passes against it.
  • node --test log-shipper/budget.test.mjs log-shipper/profile.test.mjs scripts/tc959-docker.test.mjs scripts/tc959-readiness.test.mjs: 41 pass, 0 fail. node scripts/tc959-check.mjs: passed.
  • No release notes or CHANGELOG entry: release-plz here does not bump or write entries; the changelog is written by a human at release time (docs/releasing.md). Not deployed, not merged.

test-ruling: TC-1777

dryrun added 3 commits October 25, 2026 20:50
named_keys_v1 (default false) is sealed into the Phala env as NAMED_KEYS_V1
beside DSTACK_AUTHORIZED_KEYS, so the flip is a normal dispatch and never a
hand `phala deploy -e`. The dstack-postgres compose maps it to
TINYCLOUD_ENCRYPTION_NETWORK__NAMED_KEYS_V1, sets the deletion ledger path and
mounts a deletion-ledger volume; the N0 template hash is updated to match.

Details: TC-1777
…edger mount in the compose proof

The sealed-config preflight now passes NAMED_KEYS_V1 and the compose's deletion
ledger path to --validate-config. The hosted compose proof expected the
tinycloud service to mount only the dstack socket; it now also expects the
deletion-ledger volume.

Details: TC-1777
@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-1777 (reviewed exact head 9d40773)
This head is a plain merge of main d328eb4 into the reviewed head 81bfe46; the non-CHANGELOG patch-id is unchanged (52891a74...), behind main 0. test-ruling: TC-1777 is in the PR body (Naomi ruled).

@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-1777 (reviewed exact head 7d95d89)
This head is a plain merge of main 58d4876 into the reviewed head 9d40773; the non-CHANGELOG patch-id is unchanged (52891a74...), behind main 0.

@samgbafa
samgbafa marked this pull request as ready for review October 26, 2026 00:34
@samgbafa
samgbafa merged commit 03ad48b into main Oct 26, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant