Skip to content

feat(control-plane): wire real injectSecrets/revokeSecrets against the main app's token broker - #8081

Merged
JSONbored merged 1 commit into
mainfrom
control-plane-secret-driver
Jul 22, 2026
Merged

feat(control-plane): wire real injectSecrets/revokeSecrets against the main app's token broker#8081
JSONbored merged 1 commit into
mainfrom
control-plane-secret-driver

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Implements #8066, the last piece of #7852 (itself split from #7180's provisioning core). #8064 (already merged) shipped the broker-side tenant_db_credential secret type + revoke path this calls.

  • Closes the known gap: provisionTenant already captured provisionDatabase's real connection details (Real Postgres/Hyperdrive driver for control-plane's provisionDatabase/deprovisionDatabase #7653) into its own result, but discarded them before calling injectSecrets (flagged in that function's own header comment). TenantProvisioningRequest now carries an optional database field, attached right after provisionDatabase resolves and before injectSecrets runs.
  • secret-driver.ts: a real injectSecrets/revokeSecrets implementation calling the main app's POST /v1/internal/orb/enrollments (issue, tenant_db_credential) and its new revoke route — the same two-step HTTP pattern self-hosted containers already use for their own GitHub-token exchange, just from a different physical caller (control-plane's Worker has no D1 binding and no Worker-to-Worker service-binding precedent exists in this repo). Stores the whole DatabaseConnectionDetails object (JSON-encoded), not just the bare connectionString.
  • Scope is deliberately narrow, per Wire control-plane's real injectSecrets/revokeSecrets against the broker (implements #7852) #8066's own boundary: this only stores/revokes custody of the credential in the broker — not delivery into a running container's environment (separate, not-yet-built infrastructure; a container's own bootstrap would need to exchange its own enrollment secret independently, the same way self-host already does).
  • injectSecrets now returns an opaque secretRef (the broker's enrollId) instead of void. provisionTenant threads it into its own result; http-app.ts persists it on the tenant registry record (product-agnostic, unlike amsSchedule/orbInstallationId — either product can have a real secret driver configured); DELETE /v1/tenants/:name reads it back and passes it into deprovisionTenant's new optional secretRef parameter so revokeSecrets knows what to revoke on teardown. Idempotent: a request with no secretRef never calls the broker at all.
  • withRealSecretDriver (driver-factory.ts) composes the real driver in when MAIN_APP_BASE_URL/INTERNAL_JOB_TOKEN are both configured, mirroring withRealDatabaseDriver/withRealContainerDriver's existing composition shape.
  • The GitHub-token type's existing behavior, and every other driver step, are completely unchanged.

Test plan

  • npm run build (typecheck) clean
  • npm run cf:typecheck clean
  • npm run cf:typegen — regenerated worker-configuration.d.ts for the new MAIN_APP_BASE_URL var, committed
  • npm run test:node — 179/179 passing
  • node ../scripts/control-plane-coverage.mjs — every touched file 100%/100%/100%/100%; only gap is the pre-existing, untouched settlement-backend-driver.ts
  • npx wrangler deploy --dry-run clean, both container images build, all bindings (including the new MAIN_APP_BASE_URL var) resolve
  • npm audit --audit-level=moderate — pre-existing findings only, no dependency changes in this PR

Closes #8066

…e main app's token broker (#8066)

Closes the gap #7852's control-plane wiring left open: provisionTenant already
captured provisionDatabase's real connection details (#7653) into its own
result, but discarded them before calling injectSecrets. TenantProvisioningRequest
now carries an optional `database` field, attached by provisionTenant right
after provisionDatabase resolves and before injectSecrets runs.

Adds secret-driver.ts: a real injectSecrets/revokeSecrets implementation
calling the main app's own /v1/internal/orb/enrollments (issue, #8064's
tenant_db_credential secret type) and its new revoke route -- the same
two-step HTTP pattern self-hosted containers already use for their own
GitHub-token exchange, just from a different physical caller. Stores the
WHOLE DatabaseConnectionDetails object (JSON-encoded), not just the bare
connectionString. Scope is deliberately narrow: this only stores/revokes
custody of the credential in the broker, not delivery into a running
container's environment (separate, not-yet-built infrastructure).

injectSecrets now returns an opaque `secretRef` (the broker's enrollId)
instead of void; provisionTenant threads it into its own result, http-app.ts
persists it on the tenant registry record (product-agnostic, unlike
amsSchedule/orbInstallationId), and DELETE /v1/tenants/:name reads it back to
pass into deprovisionTenant's new optional secretRef parameter, so
revokeSecrets knows what to revoke on teardown. Idempotent: a request with no
secretRef never calls the broker at all.

withRealSecretDriver (driver-factory.ts) composes the real driver in when
MAIN_APP_BASE_URL/INTERNAL_JOB_TOKEN are both configured, mirroring
withRealDatabaseDriver/withRealContainerDriver's existing composition shape.
The GitHub-token type's existing behavior, and every other driver step, are
completely unchanged.

This is the last piece of #7852 (itself split from #7180's provisioning
core) -- #8064 shipped the broker-side secret type + revoke path this calls.

Closes #8066
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 22, 2026
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.47%. Comparing base (ed9e296) to head (2bdf0a6).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8081      +/-   ##
==========================================
- Coverage   91.99%   91.47%   -0.52%     
==========================================
  Files         752      753       +1     
  Lines       76979    77157     +178     
  Branches    23315    23330      +15     
==========================================
- Hits        70820    70583     -237     
- Misses       5053     5515     +462     
+ Partials     1106     1059      -47     
Flag Coverage Δ
control-plane 99.84% <100.00%> (+0.01%) ⬆️
shard-1 54.22% <ø> (-0.71%) ⬇️
shard-2 53.48% <ø> (-0.66%) ⬇️
shard-3 53.47% <ø> (-0.54%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
control-plane/src/driver-factory.ts 100.00% <100.00%> (ø)
control-plane/src/http-app.ts 100.00% <100.00%> (ø)
control-plane/src/index.ts 100.00% <100.00%> (ø)
control-plane/src/provisioning.ts 100.00% <100.00%> (ø)
control-plane/src/secret-driver.ts 100.00% <100.00%> (ø)
control-plane/src/tenant-provisioning-driver.ts 100.00% <100.00%> (ø)
control-plane/src/tenant-registry.ts 100.00% <100.00%> (ø)

... and 3 files with indirect coverage changes

@JSONbored
JSONbored merged commit f442184 into main Jul 22, 2026
14 checks passed
@JSONbored
JSONbored deleted the control-plane-secret-driver branch July 22, 2026 21:33
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.

Wire control-plane's real injectSecrets/revokeSecrets against the broker (implements #7852)

1 participant