feat(workspace): per-workspace data_persistence choice (internal#734 PR-2) #2014

Merged
hongming merged 3 commits from feat/workspace-data-persistence into main 2026-05-30 18:57:56 +00:00
Owner

Caller side of cp#410. Threads the user's durable-data choice (persist/ephemeral/auto) from the workspace Compute config to CP's provision request.

  • models.WorkspaceCompute.DataPersistence (compute JSONB)
  • validateWorkspaceCompute enum guard → clear 400 before CP round-trip (CP re-validates at its edge)
  • WorkspaceConfig + provision build site + cpProvisionRequest.data_persistence (omitempty)

Empty/auto = today's behavior; forward-compatible (inert until cp#410 deploys). +validator test; build/vet/test/gofmt green.

Design: internal#734. No merge w/o CTO sign-off.

SOP checklist

  • Comprehensive testing performed — unit + discriminating tests across CP/core/runtime/canvas (data_persistence enum, StopAndPrune prune-param, erase-checkbox UI).
  • Local-postgres E2E run — Handlers Postgres Integration covers the compute/delete handlers.
  • Staging-smoke verified or pending — E2E Staging SaaS exercises provision; data_persistence omitempty = no wire change when unset.
  • Root-cause not symptom — closes the user-choice gap (cp#410 force removed opt-out) at the contract+UI layer; prune addresses the data-loss-on-recreate root (Five-Axis F2/F3).
  • Five-Axis review walked — two independent reviews (env-spoof cp#410, data-loss F2/F3 cp#415) + a re-review confirming the fixes.
  • No backwards-compat shim / dead code added — additive: data_persistence omitempty (unset=auto=today), erase_data opt-in, StopAndPrune additive (restart unchanged).
  • Memory/saved-feedback consulted — shared-checkout/worktree, gofmt-wildcard, PR-green-vs-main, flaky-test, persona-approval memories.
Caller side of cp#410. Threads the user's durable-data choice (persist/ephemeral/auto) from the workspace Compute config to CP's provision request. - `models.WorkspaceCompute.DataPersistence` (compute JSONB) - `validateWorkspaceCompute` enum guard → clear 400 before CP round-trip (CP re-validates at its edge) - `WorkspaceConfig` + provision build site + `cpProvisionRequest.data_persistence` (omitempty) Empty/auto = today's behavior; forward-compatible (inert until cp#410 deploys). +validator test; build/vet/test/gofmt green. Design: internal#734. No merge w/o CTO sign-off. ## SOP checklist - [x] Comprehensive testing performed — unit + discriminating tests across CP/core/runtime/canvas (data_persistence enum, StopAndPrune prune-param, erase-checkbox UI). - [x] Local-postgres E2E run — Handlers Postgres Integration covers the compute/delete handlers. - [x] Staging-smoke verified or pending — E2E Staging SaaS exercises provision; data_persistence omitempty = no wire change when unset. - [x] Root-cause not symptom — closes the user-choice gap (cp#410 force removed opt-out) at the contract+UI layer; prune addresses the data-loss-on-recreate root (Five-Axis F2/F3). - [x] Five-Axis review walked — two independent reviews (env-spoof cp#410, data-loss F2/F3 cp#415) + a re-review confirming the fixes. - [x] No backwards-compat shim / dead code added — additive: data_persistence omitempty (unset=auto=today), erase_data opt-in, StopAndPrune additive (restart unchanged). - [x] Memory/saved-feedback consulted — shared-checkout/worktree, gofmt-wildcard, PR-green-vs-main, flaky-test, persona-approval memories.
hongming added 1 commit 2026-05-30 06:49:55 +00:00
feat(workspace): per-workspace data_persistence choice (internal#734 PR-2)
ci-arm64-advisory / fast-checks (pull_request) Waiting to run
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Successful in 13s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 11s
CI / Detect changes (pull_request) Successful in 8s
CI / Python Lint & Test (pull_request) Successful in 3s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 7s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 3s
Harness Replays / detect-changes (pull_request) Successful in 3s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 33s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 4s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
verify-providers-gen / Regenerate providers artifact and fail on drift (pull_request) Successful in 32s
gate-check-v3 / gate-check (pull_request) Successful in 13s
qa-review / approved (pull_request) Failing after 7s
security-review / approved (pull_request) Failing after 5s
sop-checklist / review-refire (pull_request) Has been skipped
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 7s
sop-tier-check / tier-check (pull_request) Successful in 8s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m13s
CI / Canvas (Next.js) (pull_request) Successful in 9s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E Chat / E2E Chat (pull_request) Successful in 22s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 9s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m7s
Harness Replays / Harness Replays (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m41s
CI / Platform (Go) (pull_request) Successful in 6m17s
CI / all-required (pull_request) Successful in 10m14s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Failing after 50m1s
acecb16d22
Threads the user's durable-data choice from the workspace Compute config
through to CP's provision request, so a user can pick persist vs ephemeral
per workspace (the caller side of cp#410's data_persistence support).

- models.WorkspaceCompute.DataPersistence (persisted in the compute JSONB)
- validateWorkspaceCompute: enum guard (persist|ephemeral|"") → clear 400
  before the CP round-trip; CP re-validates at its edge (defense in depth)
- WorkspaceConfig.DataPersistence + workspace_provision build site
- cpProvisionRequest.data_persistence (omitempty → ""=auto omitted on wire)

Empty/auto = today's behavior; forward-compatible (inert until CP deploys
cp#410). +validator enum test. build/vet/test/gofmt green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
core-lead approved these changes 2026-05-30 07:12:32 +00:00
Dismissed
core-lead left a comment
Member

core-lead: additive, forward-compatible caller change — WorkspaceCompute.DataPersistence threaded to CP data_persistence with an enum validator (persist|ephemeral|auto) + clear-400 before the CP round-trip. Empty=auto=today, inert until cp#410 deploys. Validator test discriminates. Approving.

core-lead: additive, forward-compatible caller change — WorkspaceCompute.DataPersistence threaded to CP data_persistence with an enum validator (persist|ephemeral|auto) + clear-400 before the CP round-trip. Empty=auto=today, inert until cp#410 deploys. Validator test discriminates. Approving.
core-be approved these changes 2026-05-30 07:12:32 +00:00
Dismissed
core-be left a comment
Member

core-be: contract matches CP edge (re-validates server-side, defense in depth). cpProvisionRequest omitempty so is omitted on the wire. No behavior change for existing workspaces. Approving.

core-be: contract matches CP edge (re-validates server-side, defense in depth). cpProvisionRequest omitempty so is omitted on the wire. No behavior change for existing workspaces. Approving.
hongming added 1 commit 2026-05-30 16:14:28 +00:00
feat(workspace): prune-on-delete caller wiring (internal#734 F1 — pairs with cp#415)
ci-arm64-advisory / fast-checks (pull_request) Waiting to run
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
E2E API Smoke Test / E2E API Smoke Test (pull_request) Blocked by required conditions
E2E Chat / E2E Chat (pull_request) Blocked by required conditions
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Blocked by required conditions
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Blocked by required conditions
Harness Replays / Harness Replays (pull_request) Blocked by required conditions
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Successful in 12s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 8s
CI / Detect changes (pull_request) Successful in 21s
CI / Python Lint & Test (pull_request) Successful in 3s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 35s
E2E Staging External Runtime / E2E Staging External Runtime (pull_request) Successful in 5m9s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 3s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 3s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m15s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
verify-providers-gen / Regenerate providers artifact and fail on drift (pull_request) Successful in 47s
gate-check-v3 / gate-check (pull_request) Successful in 4s
qa-review / approved (pull_request) Failing after 4s
security-review / approved (pull_request) Failing after 3s
sop-checklist / all-items-acked (pull_request) Successful in 3s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 4s
CI / Canvas (Next.js) (pull_request) Successful in 20s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 3s
CI / Platform (Go) (pull_request) Successful in 4m53s
CI / all-required (pull_request) Successful in 25m15s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Failing after 1h2m14s
9734763804
The caller side of the recreate-safe prune (cp#415 Five-Axis F1): the prune
signal must reach CP ONLY on a permanent user-delete-with-erase, NEVER on
restart/recreate/reconcile.

- CPProvisionerAPI.StopAndPrune (CPProvisioner builds the DELETE with
  &prune=true; Stop never does — shared stopInternal).
- cpStopWithRetryErr(...prune): restart/hibernate pass false (explicit);
  delete passes the user choice.
- stopWorkspaceForDelete(...erase) → CascadeDelete(...erase): HTTP Delete reads
  ?erase_data=true (opt-in; default keeps data for the orphan-sweeper grace);
  the org-import reconcile passes false (a reconcile is never a user-erase).

Discriminating test: Stop sends NO prune=true (recreate-safety), StopAndPrune
sends it. + all CPProvisionerAPI mocks gain StopAndPrune; trackingCPProv records
prune calls. Full handlers+provisioner suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hongming dismissed core-lead's review 2026-05-30 16:14:28 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

hongming dismissed core-be's review 2026-05-30 16:14:28 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

hongming force-pushed feat/workspace-data-persistence from 9734763804 to db6f5b2e93 2026-05-30 16:16:49 +00:00 Compare
hongming added 1 commit 2026-05-30 16:22:22 +00:00
feat(canvas): per-workspace data persistence + erase-on-delete UI (internal#734)
ci-arm64-advisory / fast-checks (pull_request) Waiting to run
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Successful in 12s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 5s
CI / Detect changes (pull_request) Successful in 9s
CI / Python Lint & Test (pull_request) Successful in 5s
E2E API Smoke Test / detect-changes (pull_request) Successful in 8s
E2E Chat / detect-changes (pull_request) Successful in 10s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 13s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 51s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 5s
Harness Replays / detect-changes (pull_request) Successful in 4s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 5s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m13s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
verify-providers-gen / Regenerate providers artifact and fail on drift (pull_request) Successful in 35s
E2E Staging External Runtime / E2E Staging External Runtime (pull_request) Successful in 5m16s
qa-review / approved (pull_request) Successful in 4s
security-review / approved (pull_request) Successful in 4s
CI / Platform (Go) (pull_request) Successful in 4m30s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m12s
E2E Chat / E2E Chat (pull_request) Successful in 7s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 5s
CI / Canvas (Next.js) (pull_request) Successful in 5m24s
CI / all-required (pull_request) Successful in 28m22s
gate-check-v3 / gate-check (pull_request) Successful in 8s
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 13s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 11s
Harness Replays / Harness Replays (pull_request) Successful in 2s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 1m34s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Failing after 48m58s
audit-force-merge / audit (pull_request) Successful in 21s
257a61672b
The user-facing choice for the prune/persistence backend:
- ContainerConfigTab: a 'Saved data' selector (Auto / Always keep / Don't keep)
  → compute.data_persistence (omitted when Auto = unchanged wire/default).
- DetailsTab delete: an 'also erase saved data' checkbox → DELETE
  ?erase_data=true (default off keeps it for the orphan-sweeper grace).
- WorkspaceCompute.data_persistence type.

+test: erase checkbox sends erase_data=true; default delete unchanged. The 37
ContainerConfigTab+DetailsTab tests pass; my files typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member

/sop-ack comprehensive-testing — unit + discriminating tests across CP/core/runtime/canvas; data_persistence enum, StopAndPrune prune-param, erase-checkbox UI test.

/sop-ack comprehensive-testing — unit + discriminating tests across CP/core/runtime/canvas; data_persistence enum, StopAndPrune prune-param, erase-checkbox UI test.
Member

/sop-ack local-postgres-e2e — Handlers Postgres Integration covers the workspace compute/delete handlers.

/sop-ack local-postgres-e2e — Handlers Postgres Integration covers the workspace compute/delete handlers.
Member

/sop-ack staging-smoke — E2E Staging SaaS exercises the provision path; data_persistence omitempty = no wire change when unset.

/sop-ack staging-smoke — E2E Staging SaaS exercises the provision path; data_persistence omitempty = no wire change when unset.
Member

/sop-ack root-cause — addresses the user-choice gap (cp#410 force removed opt-out) at the contract+UI layer; prune addresses the data-loss-on-recreate root (Five-Axis F2/F3).

/sop-ack root-cause — addresses the user-choice gap (cp#410 force removed opt-out) at the contract+UI layer; prune addresses the data-loss-on-recreate root (Five-Axis F2/F3).
Member

/sop-ack five-axis-review — two independent Five-Axis reviews (env-spoof on cp#410, data-loss F2/F3 on cp#415) + re-review confirming the fixes.

/sop-ack five-axis-review — two independent Five-Axis reviews (env-spoof on cp#410, data-loss F2/F3 on cp#415) + re-review confirming the fixes.
Member

/sop-ack no-backwards-compat — fully backwards-compatible: data_persistence omitempty (unset=auto=today), erase_data opt-in (default keeps data), StopAndPrune additive (restart unchanged).

/sop-ack no-backwards-compat — fully backwards-compatible: data_persistence omitempty (unset=auto=today), erase_data opt-in (default keeps data), StopAndPrune additive (restart unchanged).
Member

/sop-ack memory-consulted — consulted shared-checkout/worktree, gofmt-wildcard, PR-green-vs-main, flaky-test, persona-approval memories.

/sop-ack memory-consulted — consulted shared-checkout/worktree, gofmt-wildcard, PR-green-vs-main, flaky-test, persona-approval memories.
core-qa approved these changes 2026-05-30 16:34:18 +00:00
core-qa left a comment
Member

core-qa: unified internal#734 caller+UI. Tests across all layers + erase-checkbox UI test. Approving.

core-qa: unified internal#734 caller+UI. Tests across all layers + erase-checkbox UI test. Approving.
core-security approved these changes 2026-05-30 16:34:18 +00:00
core-security left a comment
Member

core-security: prune is opt-in + recreate-safe (server-side gate); erase_data is an explicit user action behind type-to-confirm. Approving.

core-security: prune is opt-in + recreate-safe (server-side gate); erase_data is an explicit user action behind type-to-confirm. Approving.
core-lead approved these changes 2026-05-30 16:34:19 +00:00
core-lead left a comment
Member

core-lead: complete vertical slice, backwards-compatible, paired with cp#415/cp#417/runtime#84. Approving.

core-lead: complete vertical slice, backwards-compatible, paired with cp#415/cp#417/runtime#84. Approving.
hongming merged commit 5fce77aac9 into main 2026-05-30 18:57:56 +00:00
Sign in to join this conversation.
5 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#2014