feat(deploy): Slice A — hdb_deployment system table + audit record per deploy#655
Open
kriszyp wants to merge 3 commits into
Open
feat(deploy): Slice A — hdb_deployment system table + audit record per deploy#655kriszyp wants to merge 3 commits into
kriszyp wants to merge 3 commits into
Conversation
Slice A of #641. Every deploy_component call now writes a row to a new system.hdb_deployment table capturing the project, package identifier, sha256 of the payload tarball, payload size, status (pending → success or failed), error info, and the upload payload itself as a Blob attribute. The deployment_id is returned in the deploy response and is the join key Studio/CLI will use to subscribe to live progress in Slice B. Includes: - json/systemSchema.json: hdb_deployment table definition (deployment_id hash, with attributes mirroring the lifecycle) - utility/hdbTerms.ts: SYSTEM_TABLE_NAMES.DEPLOYMENT_TABLE_NAME + LIST_DEPLOYMENTS / GET_DEPLOYMENT / GET_DEPLOYMENT_PAYLOAD / DELETE_DEPLOYMENT_PAYLOAD operation enums - upgrade/directives/5-2-0.ts: provisions the table on existing installs (fresh installs get it via mount_hdb's systemSchema iteration) - components/deploymentRecorder.ts: lifecycle wrapper used by deployComponent — creates the row up front, ingests the payload into a Blob attribute with sha256 + size, then commits success or failure - components/deploymentOperations.ts: handlers for list_deployments (with project/status/since/until/limit/offset filters) and get_deployment; payload bytes are stripped from these responses - components/operations.js: deployComponent now wraps prepareApplication in a try/catch driven by the recorder; payload is re-sourced from the persisted blob so extraction reads exactly what was recorded - server/serverHelpers/serverUtilities.ts: registers the two new ops - integrationTests/deploy/deploy-tracking.test.ts: end-to-end coverage for the happy path, list filtering, and failure recording Updates the brittle deepStrictEqual deploy-response assertions in 4 existing tests to allow the new deployment_id field. Slice A scope is deliberately single-node; Slice B will replace the in-memory buffer in ingestPayload with a streaming variant and add peer-side reads from the replicated blob. Refs #641 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
Reviewed; no blockers found. The prior finding (missing |
- Skip recording on replicated executions: peer nodes receiving deploy_component via replicateOperation already have req._deploymentId set by origin, so they no longer spin up a fresh recorder + UUID + row. Prevents N duplicate rows per N-node cluster. - Cap payload at 200 MiB while Slice A buffers in memory. Throws a clear ClientError pointing users at the package-identifier path or Slice B's streaming variant. - Register list_deployments and get_deployment in utility/operation_authorization.ts. Pattern matches get_components: requires_su=true with the operation enum as the named exception so a role can be granted it without SU rights (per the design's permission model). - Add "audit": true to hdb_deployment in systemSchema.json so fresh installs match the audit setting the 5-2-0 upgrade directive applies. - Drop two now-unused imports (Transform from recorder, existsSync from test). - Auto-format pass via npm run format:write. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ap pattern Two non-obvious findings from #641 Slice A that future agents should know: 1. createBlob(readable) + table.put() doesn't synchronously drain the source. The blob's saveBlob runs concurrently; calling hash.digest() after the put resolves can race a still-flushing Transform and throw ERR_CRYPTO_HASH_FINALIZED. 2. Adding a new system table requires three changes: systemSchema.json (fresh installs), SYSTEM_TABLE_NAMES (constant), and an upgrade directive registered in directivesController.ts. The directive shape was undocumented after the .ts refactor cleared old directives. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Slice A of #641. Every
deploy_componentcall now writes a row to a newsystem.hdb_deploymenttable capturing what was deployed, when, by whom, and whether it succeeded — plus the payload tarball itself as a Blob attribute. Thedeployment_idis returned in the deploy response and is the join key Studio/CLI will use to subscribe to live progress in Slice B.This is the foundation layer for the broader deployment tracking, replicated payload delivery, and rollback design. Slices B and C will extend the same table with live
ProgressEmitterintegration (replacing #531), peer-side reads from the replicated blob (replacing #536/harper-pro#146), and rollback semantics.Changes
hdb_deploymenttable withdeployment_id(UUID hash) plus the full lifecycle attributesmount_hdb'ssystemSchemaiteration)deployComponent— creates the pending row, ingests payload into the Blob attribute with sha256 + size, commits the terminal statuslist_deployments(filters: project, status, since, until, limit, offset) andget_deployment. Payload bytes are stripped from both — onlypayload_blob_present: booleanis exposeddeployComponentwrapsprepareApplicationin a try/catch driven by the recorder; payload is re-sourced from the persisted blob so extraction reads exactly what was recordeddeepStrictEqualdeploy-response assertions in 4 existing tests updated to allow the newdeployment_idfieldScope deliberately deferred
ingestPayloadcurrently buffers the upload before persisting (race-free; multi-GB optimization comes in Slice B alongside theProgressEmittersubscriber that also benefits from chunk-level progress events)hdb_deploymentrow's blob, replacing the staging temp file (feat(deploy): stage streamed payloads to a temp file for replication #536) and the direct-HTTPS relay (harper-pro#146)deploy_component {rollback_from}arg +onStorageReclamationhook for per-node blob pruningTest plan
integrationTests/deploy/deploy-tracking.test.ts— happy-path row write,list_deploymentsfiltering, failure recording (4/4 pass locally)deploy-multipart-stream.test.tsregression check (3/3 pass)deploy-from-source.test.tsregression check (4/4 pass)npm run format:checkclean on touched filesoxlintclean on touched filesRefs #641
🤖 Generated with Claude Code