@sema-agent/server 7.150.0 → 7.152.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +451 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +144 -87
- package/deploy/sema-up/README.md +11 -4
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +7 -6
- package/deploy/sema-up/kube-up.sh +6 -6
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +12 -14
- package/dist/approval-gate-currency.d.ts +9 -9
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +3 -6
- package/dist/bind-host.js +4 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +9 -14
- package/dist/boot/execution-env.js +85 -22
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +6 -1
- package/dist/boot/reapers.js +13 -2
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +43 -48
- package/dist/boot/runner-deps.d.ts +46 -35
- package/dist/boot/runner-deps.js +94 -91
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +9 -5
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +3 -2
- package/dist/boot/stage-06-runners.d.ts +9 -4
- package/dist/boot/stage-06-runners.js +24 -9
- package/dist/boot/stage-07-capability-layer.d.ts +8 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +8 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +12 -5
- package/dist/boot/stage-09-leader.js +14 -5
- package/dist/boot/stage-10-http-server.d.ts +19 -5
- package/dist/boot/stage-10-http-server.js +14 -21
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +5 -8
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +43 -32
- package/dist/capability-facts.js +45 -51
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +26 -22
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +20 -8
- package/dist/config-invariants.js +55 -12
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +38 -42
- package/dist/config.d.ts +58 -7
- package/dist/config.js +90 -40
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +7 -0
- package/dist/device-ws-hub.js +10 -3
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/elicitation.js +2 -2
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +29 -0
- package/dist/execution-env-refusal.js +8 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/fleet/engine-signal.d.ts +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +18 -3
- package/dist/host-decision.d.ts +11 -11
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +10 -7
- package/dist/http/checkpoint-ctx.d.ts +4 -0
- package/dist/http/checkpoint-ctx.js +2 -0
- package/dist/http/dispatch.d.ts +8 -3
- package/dist/http/dispatch.js +59 -32
- package/dist/http/durable-run-leg.js +16 -17
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +3 -1
- package/dist/http/owner-access.d.ts +33 -14
- package/dist/http/owner-access.js +40 -10
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +42 -3
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +367 -117
- package/dist/http/route-ctx.d.ts +91 -15
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +5 -1
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +99 -51
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +38 -10
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +171 -65
- package/dist/http/routes/session-sync.d.ts +22 -9
- package/dist/http/routes/session-sync.js +204 -107
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +30 -15
- package/dist/http/routes/tasks.js +46 -41
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +30 -30
- package/dist/http/server.js +16 -4
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +7 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +2 -2
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +116 -11
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +23 -11
- package/dist/memory-scope.js +18 -6
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +25 -17
- package/dist/observability/fail-open.js +25 -17
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +2 -2
- package/dist/parked-decide.d.ts +106 -55
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/permission-mode-admission.d.ts +74 -5
- package/dist/permission-mode-admission.js +56 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +14 -2
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
- package/dist/plugins/approval-ask-store-memory.js +35 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
- package/dist/plugins/approval-ask-store-sql.js +45 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +104 -80
- package/dist/plugins/one-time-migrations.js +226 -132
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +35 -10
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +46 -10
- package/dist/plugins/remote-env-host.js +124 -52
- package/dist/plugins/remote-env-k8s.d.ts +109 -41
- package/dist/plugins/remote-env-k8s.js +160 -54
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +5 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/sql-json-column.d.ts +1 -1
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +84 -15
- package/dist/plugins/store-backend.js +236 -72
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +14 -1
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +21 -25
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-custody.d.ts +4 -3
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +9 -9
- package/dist/runs.d.ts +54 -16
- package/dist/runs.js +67 -13
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +25 -103
- package/dist/session-sync.js +14 -76
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
- package/dist/stores-sql/file-history-store-sql.js +205 -95
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +1 -9
- package/dist/stores-sql/retention-store-sql.js +5 -19
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +2 -2
- package/dist/task-settings.d.ts +7 -5
- package/dist/task-settings.js +3 -3
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +465 -507
- package/dist/tool-approval.js +606 -1222
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +571 -178
- package/dist/trace/self-minted-wire.js +189 -56
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
- package/package.json +7 -3
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.151.0.json +762 -0
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -5,7 +5,7 @@ export declare const REPLICA_REGISTRATION_TABLE = "replica_registration";
|
|
|
5
5
|
* 本构建的能力名单(常设、只增):每一条读停-迁-起证据的一次性迁移一个名。删码之后名字留着 —— 名单只增不减(钉:`test/replica-registration.test.ts`)。
|
|
6
6
|
* 守卫读证据时传的名在型上就要在这里(`ReplicaCapability`):不在名单里的迁移读不了证据,编译期红。
|
|
7
7
|
*/
|
|
8
|
-
export declare const REPLICA_CAPABILITIES: readonly ["M40", "M41", "M42", "M43", "M51"];
|
|
8
|
+
export declare const REPLICA_CAPABILITIES: readonly ["M40", "M41", "M42", "M43", "M51", "M54"];
|
|
9
9
|
export type ReplicaCapability = (typeof REPLICA_CAPABILITIES)[number];
|
|
10
10
|
/** 留存视界(写者钟):登记早于此的别人的行在下一次登记时删。量级取远大于任一副本的寿命与副本间钟差。 */
|
|
11
11
|
export declare const REPLICA_REGISTRATION_HORIZON_MS: number;
|
|
@@ -2,7 +2,7 @@ import { hostname } from "node:os";
|
|
|
2
2
|
import { processInstanceId } from "../process-instance.js";
|
|
3
3
|
import { serviceVersion } from "../service-version.js";
|
|
4
4
|
export const REPLICA_REGISTRATION_TABLE = "replica_registration";
|
|
5
|
-
export const REPLICA_CAPABILITIES = ["M40", "M41", "M42", "M43", "M51"];
|
|
5
|
+
export const REPLICA_CAPABILITIES = ["M40", "M41", "M42", "M43", "M51", "M54"];
|
|
6
6
|
export const REPLICA_REGISTRATION_HORIZON_MS = 90 * 24 * 60 * 60 * 1000;
|
|
7
7
|
export function buildThisReplicaRegistration() {
|
|
8
8
|
return { instanceId: processInstanceId(), releaseLine: serviceVersion(), capabilities: REPLICA_CAPABILITIES, hostName: hostname(), pid: process.pid };
|
|
@@ -17,14 +17,23 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
19
19
|
import type { Pool as PgPool } from "pg";
|
|
20
|
-
import { type SqlDriver } from "./sql-driver.js";
|
|
20
|
+
import { type SqlDialect, type SqlDriver, type SqlExec } from "./sql-driver.js";
|
|
21
|
+
/**
|
|
22
|
+
* 一条锚的写(幂等 upsert,主键 `(session_id, event_id)`)—— **语句源**,跑在调用方给的执行口上:落定段(`landed-attendants.ts`:段首锁根行判过住客,
|
|
23
|
+
* 同一事务)是生产里唯一的调用方;店的 {@link SqlResumeAnchorStore.put} 是夹具 / 契约面的同一句。
|
|
24
|
+
*/
|
|
25
|
+
export declare function putAnchorOn(exec: Pick<SqlExec, "query">, dialect: SqlDialect, sessionId: string, eventId: string, entryId: string, owner: string | null): Promise<void>;
|
|
26
|
+
/** 一只会话的锚全删(按 `session_id` 定址)—— 语句源(落定段的擦除腿与 E21 删除同一句)。返回删掉的行数。 */
|
|
27
|
+
export declare function deleteAnchorsOn(exec: Pick<SqlExec, "query">, dialect: SqlDialect, sessionId: string): Promise<number>;
|
|
21
28
|
/** Dual-dialect durable resume-at anchor map. See the file header for the dialect-delta ledger. */
|
|
22
29
|
export declare class SqlResumeAnchorStore {
|
|
23
30
|
protected readonly db: SqlDriver;
|
|
24
31
|
constructor(db: SqlDriver);
|
|
25
32
|
/** Pick the dialect's SQL text. Both statements stay written out at the call site ON PURPOSE. */
|
|
26
33
|
private q;
|
|
27
|
-
/** Record/overwrite the anchor for one settled message boundary (idempotent upsert on the (session_id,event_id) PK).
|
|
34
|
+
/** Record/overwrite the anchor for one settled message boundary (idempotent upsert on the (session_id,event_id) PK). **Not a production writer**:
|
|
35
|
+
* the deployment's read face (`StoreBackend.resumeAnchor()`'s `ResumeAnchorStore`) carries no `put` — every production anchor write goes through the landed section
|
|
36
|
+
* (`landed-attendants.ts`), which runs {@link putAnchorOn} after locking the session row and judging the occupant. Fixtures seed through this verb. */
|
|
28
37
|
put(sessionId: string, eventId: string, entryId: string, owner: string | null): Promise<void>;
|
|
29
38
|
/** Resolve a shell-supplied eventId → the persisted SessionTreeEntry.id; undefined = unknown anchor. */
|
|
30
39
|
resolve(sessionId: string, eventId: string, owner: string | null): Promise<string | undefined>;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
2
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
3
|
+
export async function putAnchorOn(exec, dialect, sessionId, eventId, entryId, owner) {
|
|
4
|
+
await exec.query(dialect === "mysql"
|
|
5
|
+
? "INSERT INTO resume_anchor (session_id, event_id, entry_id, owner, created_at) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE entry_id = VALUES(entry_id), owner = VALUES(owner)"
|
|
6
|
+
: "INSERT INTO resume_anchor (session_id, event_id, entry_id, owner, created_at) VALUES ($1,$2,$3,$4,$5) ON CONFLICT (session_id, event_id) DO UPDATE SET entry_id = EXCLUDED.entry_id, owner = EXCLUDED.owner", [sessionId, eventId, entryId, owner, new Date()]);
|
|
7
|
+
}
|
|
8
|
+
export async function deleteAnchorsOn(exec, dialect, sessionId) {
|
|
9
|
+
return (await exec.query(dialect === "mysql" ? "DELETE FROM resume_anchor WHERE session_id = ?" : "DELETE FROM resume_anchor WHERE session_id = $1", [sessionId])).affected;
|
|
10
|
+
}
|
|
2
11
|
export class SqlResumeAnchorStore {
|
|
3
12
|
db;
|
|
4
13
|
constructor(db) {
|
|
@@ -8,9 +17,7 @@ export class SqlResumeAnchorStore {
|
|
|
8
17
|
return this.db.dialect === "mysql" ? mysql : pg;
|
|
9
18
|
}
|
|
10
19
|
async put(sessionId, eventId, entryId, owner) {
|
|
11
|
-
await this.db
|
|
12
|
-
"ON DUPLICATE KEY UPDATE entry_id = VALUES(entry_id), owner = VALUES(owner)", "INSERT INTO resume_anchor (session_id, event_id, entry_id, owner, created_at) VALUES ($1,$2,$3,$4,$5) " +
|
|
13
|
-
"ON CONFLICT (session_id, event_id) DO UPDATE SET entry_id = EXCLUDED.entry_id, owner = EXCLUDED.owner"), [sessionId, eventId, entryId, owner, new Date()]);
|
|
20
|
+
await putAnchorOn(this.db, this.db.dialect, sessionId, eventId, entryId, owner);
|
|
14
21
|
}
|
|
15
22
|
async resolve(sessionId, eventId, owner) {
|
|
16
23
|
const { rows } = await this.db.query(this.q("SELECT entry_id FROM resume_anchor WHERE session_id = ? AND event_id = ? AND owner <=> ?", "SELECT entry_id FROM resume_anchor WHERE session_id = $1 AND event_id = $2 AND owner IS NOT DISTINCT FROM $3"), [sessionId, eventId, owner]);
|
|
@@ -21,10 +28,10 @@ export class SqlResumeAnchorStore {
|
|
|
21
28
|
return rows.map((r) => ({ eventId: String(r.event_id), entryId: String(r.entry_id), owner: r.owner == null ? null : String(r.owner) }));
|
|
22
29
|
}
|
|
23
30
|
async deleteBySession(sessionId) {
|
|
24
|
-
|
|
25
|
-
return res.affected;
|
|
31
|
+
return deleteAnchorsOn(this.db, this.db.dialect, sessionId);
|
|
26
32
|
}
|
|
27
33
|
}
|
|
34
|
+
sealStoreClass(SqlResumeAnchorStore, "sql-resume-anchor-store", { put: "exit", resolve: "exit", listBySession: "exit", deleteBySession: "exit" });
|
|
28
35
|
export class TiDBResumeAnchorStore extends SqlResumeAnchorStore {
|
|
29
36
|
constructor(pool) {
|
|
30
37
|
super(mysqlDriver(pool));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
2
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
2
3
|
export const RETENTION_AUDIT_TABLE = "retention_audit";
|
|
3
4
|
export const RETENTION_HOLD_TABLE = "retention_hold";
|
|
4
5
|
export const RETENTION_LEASE_TABLE = "retention_lease";
|
|
@@ -217,6 +218,9 @@ export class SqlRetentionLaneStore {
|
|
|
217
218
|
}));
|
|
218
219
|
}
|
|
219
220
|
}
|
|
221
|
+
sealStoreClass(SqlRetentionLaneStore, "sql-retention-lane-store", {
|
|
222
|
+
acquire: "exit", renew: "exit", release: "exit", setHold: "exit", setHoldAudited: "exit", holdInForce: "exit", appendAudit: "exit", listAudit: "exit",
|
|
223
|
+
});
|
|
220
224
|
export class TiDBRetentionLaneStore extends SqlRetentionLaneStore {
|
|
221
225
|
constructor(pool) {
|
|
222
226
|
super(mysqlDriver(pool));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* 部署表那一半)对**同一条域律**发谓词,只从这里取:一条律一个读法,两半不各写一份(分家的方向是多删或漏删)
|
|
2
|
+
* 托管留存的三只 SQL 谓词 —— 执行器(`stores-sql/retention-store-sql.ts`,引擎座表那一半)与部署的事务内钩(`plugins/retention-deployment.ts`,
|
|
3
|
+
* 部署表那一半)对**同一条域律**发谓词,只从这里取:一条律一个读法,两半不各写一份(分家的方向是多删或漏删)。第三只 —— 会话树的活引用
|
|
4
|
+
* ({@link sessionLiveReferenceSql})—— 另有会话老化的两个读者(`plugins/session-store-sql.ts` 的老化候选面与老化围栏):自动老化不许比托管留存松。
|
|
4
5
|
*
|
|
5
6
|
* 域 = 租户键:`COALESCE(session_meta.owner, '')` / `checkpoint.scope` 原样;**空串 `''` = 无主(anonymous/dev)桶**,谓词写成
|
|
6
7
|
* `(owner IS NULL OR owner = '')` —— 合并只发生在无主侧,永远伸不进一个真租户;拆成两个桶才会漏(NULL 那半永不被枚举)。
|
|
@@ -26,4 +27,21 @@ export declare function retentionIdSet(dialect: SqlDialect, col: string, ids: re
|
|
|
26
27
|
sql: string;
|
|
27
28
|
params: unknown[];
|
|
28
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* **会话树的活引用 —— SQL 谓词的唯一写法**(`sm` = `session_meta` 的别名;两方言一只函数)。
|
|
32
|
+
*
|
|
33
|
+
* 读者三只,同调这一只:托管留存的「可删候选」(否定)与「被保护计数」(肯定)(`stores-sql/retention-store-sql.ts` 的 `liveReferenceExists`)、会话老化的候选面与
|
|
34
|
+
* 老化围栏的锁内重判(`plugins/session-store-sql.ts`;会话种类的律在 `src/session-kind.ts`)。两份手抄必然在某次改动后分家,而分家的方向是**多删**(候选放宽、
|
|
35
|
+
* 计数收紧,两边都不会有人红)。local 店的同义判是 `plugins/local-session-live-reference.ts`。
|
|
36
|
+
*
|
|
37
|
+
* 腿的词表:活跑 claim / 挂起 park(pending 检查点)/ 活着的后台子代(running|parked,三根会话锚)/ 在跑的 workflow(`originatingSessionId` 住在 run blob 里 ⇒
|
|
38
|
+
* JSON 提取是真方言分叉)。fork 子代**结构上没有边**(理由见 `SqlRetentionStore.deleteExpiredSessions` 的头注)。
|
|
39
|
+
*
|
|
40
|
+
* 🔴 [ref] C18 追加的**第五条腿**(placed 分区,core 5.48 [ref] 义务 4 的 server 侧兑现):一只 `placement_kind` 在场的会话是某条委派的**转录**,它的删除权
|
|
41
|
+
* **独家**属于联合 reap(`reapDurableAgents`:先按 rev 条件删 agent 行、赢了才 `release` 终结转录;以及行已不在时的分区收割腿)。让视界腿也去删它会造出两个删除
|
|
42
|
+
* 权威,而它们的交叠恰好是这条义务要关死的那个状态:行还在、指着一份已经不存在的转录(core 的 `delegation.transcript_integrity` 通告说的就是它)。⇒ 把「placed」当成
|
|
43
|
+
* 一条**活引用**:候选谓词排除它,被保护计数同时把它记成 skipped(两侧共用本函数 ⇒ 不可能分家)。它不会因此永生:分区收割腿按 `backgroundAgentRetentionMs` 的
|
|
44
|
+
* 年龄 + 「行确实不在」联合判定后真删。
|
|
45
|
+
*/
|
|
46
|
+
export declare function sessionLiveReferenceSql(dialect: SqlDialect): string;
|
|
29
47
|
//# sourceMappingURL=retention-sql.d.ts.map
|
|
@@ -5,4 +5,15 @@ export function retentionDomainWhere(dialect, col, domain, pgIndex) {
|
|
|
5
5
|
export function retentionIdSet(dialect, col, ids, pgIndex) {
|
|
6
6
|
return dialect === "mysql" ? { sql: `${col} IN (${ids.map(() => "?").join(",")})`, params: [...ids] } : { sql: `${col} = ANY($${pgIndex}::text[])`, params: [ids] };
|
|
7
7
|
}
|
|
8
|
+
export function sessionLiveReferenceSql(dialect) {
|
|
9
|
+
const workflow = dialect === "mysql"
|
|
10
|
+
? `EXISTS (SELECT 1 FROM workflow_run wr WHERE wr.status = 'running' AND JSON_UNQUOTE(JSON_EXTRACT(wr.run, '$.originatingSessionId')) = sm.session_id)`
|
|
11
|
+
: `EXISTS (SELECT 1 FROM workflow_run wr WHERE wr.status = 'running' AND wr.run::json->>'originatingSessionId' = sm.session_id)`;
|
|
12
|
+
return (`(sm.placement_kind IS NOT NULL` +
|
|
13
|
+
` OR EXISTS (SELECT 1 FROM task_active ta WHERE ta.session_id = sm.session_id)` +
|
|
14
|
+
` OR EXISTS (SELECT 1 FROM checkpoint c2 WHERE c2.session_id = sm.session_id AND c2.status = 'pending')` +
|
|
15
|
+
` OR EXISTS (SELECT 1 FROM background_agent ba WHERE ba.status IN ('running','parked')` +
|
|
16
|
+
` AND (ba.session_id = sm.session_id OR ba.parent_session_id = sm.session_id OR ba.root_session_id = sm.session_id))` +
|
|
17
|
+
` OR ${workflow})`);
|
|
18
|
+
}
|
|
8
19
|
//# sourceMappingURL=retention-sql.js.map
|
|
@@ -3,7 +3,7 @@ import type { Pool as MySqlPool } from "mysql2/promise";
|
|
|
3
3
|
import type { Pool as PgPool } from "pg";
|
|
4
4
|
import { type UsageRow } from "../usage-analytics.js";
|
|
5
5
|
import { type RunStallWiring, type ClaimFenced, type CreateRunOutcome, type FencedRun, type NewRunMeta, type RunIdemBinding, type RunListQuery, type RunRecord, type RunEvent, type PersistedTaskResult, type LatestRunRef, type SettledLegMemoryObservation } from "./store-contracts.js";
|
|
6
|
-
import { type SqlDriver, type SqlTxConn } from "./sql-driver.js";
|
|
6
|
+
import { type SqlDialect, type SqlDriver, type SqlTxConn } from "./sql-driver.js";
|
|
7
7
|
import type { LedgerEventType } from "../trace/ledger-events.js";
|
|
8
8
|
import { type SpaceCommitClaim, type SpaceCommitReading, type SpaceCommitState } from "../workspace-space-commit.js";
|
|
9
9
|
export type { RunRecord, RunEvent, LatestRunRef } from "./store-contracts.js";
|
|
@@ -12,6 +12,25 @@ export type { RunRecord, RunEvent, LatestRunRef } from "./store-contracts.js";
|
|
|
12
12
|
* ({@link decodeResultColumn},投影须经 `jsonColumnText`);读不出 ⇒ `"unreadable"`(迁移跳过那一行、码列不动 —— 店的读腿对它照旧响亮拒)。
|
|
13
13
|
*/
|
|
14
14
|
export declare function decodeRunResultCellM44(v: unknown, taskId: string): PersistedTaskResult | null | "unreadable";
|
|
15
|
+
/** 「`running` × 心跳 × 判活窗」谓词的哪一侧:`live` = 窗内心跳过(停-迁-起证据读法选的那一批),`stale` = 窗外(死亡判决落的那一批)。 */
|
|
16
|
+
export type RunHeartbeatSide = "live" | "stale";
|
|
17
|
+
/**
|
|
18
|
+
* 🔴 **「`running` × 心跳 × 判活窗」谓词的唯一构造**(SQL 两方言):死亡判决的那一句({@link SqlRunStore} 的 `landStallVerdicts`:收割器与两处单行落判决)
|
|
19
|
+
* 与停-迁-起证据读法(`stop-then-start.ts` 的 `readOlderReplicaEvidence`)同调它 —— 同一个窗界、同一处 `>=` / `<` 边界,`task_run` 心跳比较在本仓只有这一处文本
|
|
20
|
+
* (源码门 `test/run-liveness-single-source-gate.test.ts`)。交回 WHERE 片段与它唯一的绑定参数(窗界)。
|
|
21
|
+
*
|
|
22
|
+
* **钟**:心跳由写者在绑定参数里送它自己的进程钟(本店每一句 `updated_at = ?` 都送 `new Date()`),池把它编成库里的值(MySQL 协议:池选项 `timezone: "Z"`
|
|
23
|
+
* ⇒ `DATETIME(3)` 里存 UTC 墙钟,`tidb-pool.ts` 的 `tidbPoolOptions`;PG:`TIMESTAMPTZ` 存绝对时刻)。窗界取同一种钟、经同一只池编码 —— `nowMs − windowMs` 作绑定参数,
|
|
24
|
+
* 不用库侧的 `NOW(3)`:它按会话时区答墙钟,会话时区不是 UTC 的库上与写者存下的 UTC 墙钟差出整个时区偏移(证据读法因此读空 = 守卫静默放行)。
|
|
25
|
+
* `placeholder` = 这一片段在整句里的 PG 占位符序号(MySQL 协议恒 `?`)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function runningHeartbeatPredicate(dialect: SqlDialect, side: RunHeartbeatSide, at: {
|
|
28
|
+
readonly nowMs: number;
|
|
29
|
+
readonly windowMs: number;
|
|
30
|
+
}, placeholder: number): {
|
|
31
|
+
readonly sql: string;
|
|
32
|
+
readonly param: Date;
|
|
33
|
+
};
|
|
15
34
|
export declare class SqlRunStore {
|
|
16
35
|
readonly db: SqlDriver;
|
|
17
36
|
private readonly stall;
|
|
@@ -70,7 +89,7 @@ export declare class SqlRunStore {
|
|
|
70
89
|
*/
|
|
71
90
|
private settleDueHolderOn;
|
|
72
91
|
/**
|
|
73
|
-
* 🔴 **死亡判决的那一句**(
|
|
92
|
+
* 🔴 **死亡判决的那一句**(收割器与两处单行落判决共用一只语句构造;条件 = {@link runningHeartbeatPredicate} 的 `stale` 一侧,与停-迁-起证据读法同一只):`running ∧ updated_at < 窗界` ⇒ `failed` / `result = NULL` / {@link RUN_STALLED_ERROR} /
|
|
74
93
|
* `error_code = run.stalled`,同一事务放认领。两种作用域:
|
|
75
94
|
* · **全表**(`taskId` 缺席,收割器):放掉每条非活非停驻行的认领 + 孤儿认领(语义同修前);
|
|
76
95
|
* · **单行**(`AND task_id = ?`,观察口 / 认领冲突):只有命中 1 行才 `DELETE FROM task_active WHERE task_id = ?` —— 心跳或停驻抢先赢了 CAS ⇒ 0 行 ⇒ 认领不动。
|
|
@@ -12,6 +12,7 @@ import { isDupKeyError } from "./sql-errors.js";
|
|
|
12
12
|
import { readDeletingTokenOn } from "./session-ext-table.js";
|
|
13
13
|
import { readRunIdentityCells, runIdentityCells } from "../identity-source.js";
|
|
14
14
|
import { decideSpaceCommitAbandon, decideSpaceCommitClaim, fenceSpaceCommitAtTerminal, spaceCommitStateOf } from "../workspace-space-commit.js";
|
|
15
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
15
16
|
function runRowCols(dialect) {
|
|
16
17
|
return (`task_id, session_id, owner, status, ${jsonColumnText(dialect, "result")}, error, error_code, job_id, source, ` +
|
|
17
18
|
"identity_source, identity_scope, identity_principal_inc, instance_id, leg_id, cancel_requested, objective_preview, created_at, updated_at");
|
|
@@ -60,6 +61,20 @@ function m44ErrorCodeReadSide(status, result, column) {
|
|
|
60
61
|
return column;
|
|
61
62
|
return persistedPlaneOf(result).errorCode ?? null;
|
|
62
63
|
}
|
|
64
|
+
export function runningHeartbeatPredicate(dialect, side, at, placeholder) {
|
|
65
|
+
const p = dialect === "mysql" ? "?" : `$${placeholder}`;
|
|
66
|
+
const param = new Date(at.nowMs - at.windowMs);
|
|
67
|
+
switch (side) {
|
|
68
|
+
case "live":
|
|
69
|
+
return { sql: `status = 'running' AND updated_at >= ${p}`, param };
|
|
70
|
+
case "stale":
|
|
71
|
+
return { sql: `status = 'running' AND updated_at < ${p}`, param };
|
|
72
|
+
default: {
|
|
73
|
+
const unhandled = side;
|
|
74
|
+
throw new Error(`runningHeartbeatPredicate: unknown side ${String(unhandled)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
63
78
|
export class SqlRunStore {
|
|
64
79
|
db;
|
|
65
80
|
stall;
|
|
@@ -188,7 +203,7 @@ export class SqlRunStore {
|
|
|
188
203
|
let landed = 0;
|
|
189
204
|
try {
|
|
190
205
|
await this.txOn(conn, async (c) => {
|
|
191
|
-
landed = await this.landStallVerdicts(c,
|
|
206
|
+
landed = await this.landStallVerdicts(c, { nowMs, windowMs }, holderTaskId);
|
|
192
207
|
});
|
|
193
208
|
}
|
|
194
209
|
catch (err) {
|
|
@@ -199,11 +214,12 @@ export class SqlRunStore {
|
|
|
199
214
|
this.stall.onVerdicts(landed);
|
|
200
215
|
return landed > 0;
|
|
201
216
|
}
|
|
202
|
-
async landStallVerdicts(conn,
|
|
217
|
+
async landStallVerdicts(conn, at, taskId) {
|
|
203
218
|
const one = taskId !== undefined;
|
|
219
|
+
const stale = { mysql: runningHeartbeatPredicate("mysql", "stale", at, 2), pg: runningHeartbeatPredicate("pg", "stale", at, 2) };
|
|
204
220
|
const { affected } = await conn.query(this.q(`UPDATE task_run SET status = 'failed', result = NULL, error = '${RUN_STALLED_ERROR}', error_code = '${RUN_HOLDER_DEATH_CODES.stalled}', updated_at = ? ` +
|
|
205
|
-
`WHERE
|
|
206
|
-
`WHERE
|
|
221
|
+
`WHERE ${stale.mysql.sql}${one ? " AND task_id = ?" : ""}`, `UPDATE task_run SET status = 'failed', result = NULL, error = '${RUN_STALLED_ERROR}', error_code = '${RUN_HOLDER_DEATH_CODES.stalled}', updated_at = $1 ` +
|
|
222
|
+
`WHERE ${stale.pg.sql}${one ? " AND task_id = $3" : ""}`), one ? [new Date(), stale[this.db.dialect].param, taskId] : [new Date(), stale[this.db.dialect].param]);
|
|
207
223
|
if (one) {
|
|
208
224
|
if (affected === 1)
|
|
209
225
|
await conn.query(this.q("DELETE FROM task_active WHERE task_id = ?", "DELETE FROM task_active WHERE task_id = $1"), [taskId]);
|
|
@@ -221,7 +237,7 @@ export class SqlRunStore {
|
|
|
221
237
|
let landed = 0;
|
|
222
238
|
try {
|
|
223
239
|
await this.tx(async (conn) => {
|
|
224
|
-
landed = await this.landStallVerdicts(conn,
|
|
240
|
+
landed = await this.landStallVerdicts(conn, { nowMs, windowMs }, row.taskId);
|
|
225
241
|
});
|
|
226
242
|
}
|
|
227
243
|
catch (err) {
|
|
@@ -596,10 +612,10 @@ export class SqlRunStore {
|
|
|
596
612
|
}));
|
|
597
613
|
}
|
|
598
614
|
async reapStale() {
|
|
599
|
-
const
|
|
615
|
+
const at = { nowMs: Date.now(), windowMs: this.stall.windowMs() };
|
|
600
616
|
let reaped = 0;
|
|
601
617
|
await this.tx(async (conn) => {
|
|
602
|
-
reaped = await this.landStallVerdicts(conn,
|
|
618
|
+
reaped = await this.landStallVerdicts(conn, at);
|
|
603
619
|
});
|
|
604
620
|
if (reaped > 0)
|
|
605
621
|
this.stall.onVerdicts(reaped);
|
|
@@ -635,6 +651,14 @@ export class SqlRunStore {
|
|
|
635
651
|
return reaped;
|
|
636
652
|
}
|
|
637
653
|
}
|
|
654
|
+
sealStoreClass(SqlRunStore, "sql-run-store", {
|
|
655
|
+
createRun: "exit", observeRun: "exit", fillObjectivePreview: "exit", requestCancel: "exit", isCancelRequested: "exit", requestPreempt: "exit",
|
|
656
|
+
isPreemptRequested: "exit", heartbeat: "exit", appendEvent: "exit", maxSeq: "exit", setTerminal: "exit", readSpaceCommit: "exit", claimSpaceCommit: "exit",
|
|
657
|
+
endSpaceCommit: "exit", abandonSpaceCommit: "exit", setSuspended: "exit", setNeedsReview: "exit", markResuming: "exit", whileHoldingClaim: "exit",
|
|
658
|
+
getActiveTaskId: "exit", getRun: "exit", getRunByIdem: "exit", releaseIdemKey: "exit", withdrawMintedRun: "exit", bindIdemBodyFingerprint: "exit",
|
|
659
|
+
listRuns: "exit", latestRunForSession: "exit", latestMemoryObservationForSession: "exit", deleteBySession: "exit", sourceSummary: "exit", usageScan: "exit",
|
|
660
|
+
retainedFrom: "exit", getEvents: "exit", reapStale: "exit", reapSuspended: "exit", failSuspendedWithExpiredCheckpoint: "exit",
|
|
661
|
+
});
|
|
638
662
|
export class TiDBRunStore extends SqlRunStore {
|
|
639
663
|
constructor(pool, stall) {
|
|
640
664
|
super(mysqlDriver(pool), stall);
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import { type ObjectStoreOp } from "../object-store-buckets.js";
|
|
2
|
+
/** The signed URL's lifetime under row `op` — the ONE reading of the table's TTL column. A row with no `knob` has a fixed TTL: the table's number, and a
|
|
3
|
+
* call that brings one is refused (its number would be a second source). A knob row takes `requested` (the configured value the call brings) clamped to
|
|
4
|
+
* the row's `maxSec` (the row's policy cap) — a call that brings none, or a value that is not a positive number of seconds (`0` is no lifetime at all),
|
|
5
|
+
* takes the row's `defaultSec` — the reading the `SESSION_SNAPSHOT_TTL_SEC` loader gives its `0` (any other non-positive spelling no longer loads: the configuration is refused) — and a row with no default needs a positive one.
|
|
6
|
+
* Every row, one answer for the SigV4 ceiling ({@link SIGV4_PRESIGN_MAX_SEC}): a lifetime over it is refused, never clamped (the knobs are refused above it
|
|
7
|
+
* when the configuration loads, so a call that gets here is a defect). */
|
|
8
|
+
export declare function rowTtlSec(op: ObjectStoreOp, requested: number | undefined): number;
|
|
1
9
|
export interface S3PresignParams {
|
|
10
|
+
/** The object-store action table row this request is (its action must be `method`). */
|
|
11
|
+
op: ObjectStoreOp;
|
|
2
12
|
/** Base endpoint, e.g. `http://minio.minio.svc.cluster.local:9000` (the host the SANDBOX will reach). */
|
|
3
13
|
endpoint: string;
|
|
4
14
|
bucket: string;
|
|
@@ -8,6 +18,7 @@ export interface S3PresignParams {
|
|
|
8
18
|
accessKey: string;
|
|
9
19
|
secretKey: string;
|
|
10
20
|
region?: string;
|
|
21
|
+
/** The configured TTL (seconds) of a knob row; a fixed-TTL row takes none (see {@link rowTtlSec}). */
|
|
11
22
|
expiresSec?: number;
|
|
12
23
|
/** Override the signing clock (tests). Defaults to now. */
|
|
13
24
|
now?: Date;
|
|
@@ -33,6 +44,8 @@ export declare function presignS3BucketUrl(p: S3BucketPresignParams): string;
|
|
|
33
44
|
/** ListObjectsV2 presign(D-1 孤儿对象 GC,clay 拍 2026-07-28):GET `/<bucket>/?list-type=2&prefix=…`。
|
|
34
45
|
* bucket 级 GET 是**列举能力**——只给 server 端 sweep 用,URL 绝不外发(与 copy 面同纪律)。 */
|
|
35
46
|
export declare function presignS3ListUrl(p: {
|
|
47
|
+
/** The object-store action table row this listing is (a LIST row). */
|
|
48
|
+
op: ObjectStoreOp;
|
|
36
49
|
endpoint: string;
|
|
37
50
|
bucket: string;
|
|
38
51
|
prefix: string;
|
|
@@ -45,6 +58,8 @@ export declare function presignS3ListUrl(p: {
|
|
|
45
58
|
now?: Date;
|
|
46
59
|
}): string;
|
|
47
60
|
export interface S3CopyPresignParams {
|
|
61
|
+
/** The object-store action table row this copy is (a COPY row). */
|
|
62
|
+
op: ObjectStoreOp;
|
|
48
63
|
/** INTERNAL endpoint — CopyObject is a SERVER-side request with adapter creds; never hand this URL out. */
|
|
49
64
|
endpoint: string;
|
|
50
65
|
/** Destination coordinates (the PUT target). */
|
|
@@ -69,4 +84,12 @@ export declare function presignS3CopyUrl(p: S3CopyPresignParams): {
|
|
|
69
84
|
url: string;
|
|
70
85
|
headers: Record<string, string>;
|
|
71
86
|
};
|
|
87
|
+
/** The URL of an object on an anonymous-read bucket (no signature, no expiry): `<endpoint>/<bucket>/<key>`, each key segment URI-encoded. `op` names
|
|
88
|
+
* the table's anonymous GET row; any other row is refused. */
|
|
89
|
+
export declare function buildPublicObjectUrl(p: {
|
|
90
|
+
op: ObjectStoreOp;
|
|
91
|
+
endpoint: string;
|
|
92
|
+
bucket: string;
|
|
93
|
+
key: string;
|
|
94
|
+
}): string;
|
|
72
95
|
//# sourceMappingURL=s3-presign.d.ts.map
|
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
import { createHash, createHmac } from "node:crypto";
|
|
2
|
+
import { SIGV4_PRESIGN_MAX_SEC, objectStoreActionOf } from "../object-store-buckets.js";
|
|
3
|
+
function assertRow(op, verb, signing) {
|
|
4
|
+
const row = objectStoreActionOf(op);
|
|
5
|
+
if (row.action !== verb)
|
|
6
|
+
throw new Error(`object-store seat: ${op} is a ${row.action} row — refusing to build a ${verb} request under it`);
|
|
7
|
+
if ((row.ttl === "unsigned") !== (signing === "anonymous")) {
|
|
8
|
+
throw new Error(`object-store seat: ${op} is ${row.ttl === "unsigned" ? "an anonymous" : "a signed"} row — refusing to build ${signing === "anonymous" ? "an anonymous" : "a signed"} URL under it`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function rowTtlSec(op, requested) {
|
|
12
|
+
const ttl = objectStoreActionOf(op).ttl;
|
|
13
|
+
if (ttl === "unsigned")
|
|
14
|
+
throw new Error(`object-store seat: ${op} is unsigned — it has no URL lifetime`);
|
|
15
|
+
if (ttl.knob === undefined) {
|
|
16
|
+
if (requested !== undefined)
|
|
17
|
+
throw new Error(`object-store seat: ${op} has a fixed TTL (${ttl.defaultSec} s, the table's) — refusing a call-site TTL of ${requested} s`);
|
|
18
|
+
return ttl.defaultSec;
|
|
19
|
+
}
|
|
20
|
+
const sec = requested !== undefined && requested > 0 ? requested : ttl.defaultSec;
|
|
21
|
+
if (sec === undefined)
|
|
22
|
+
throw new Error(`object-store seat: ${op} takes its TTL from ${ttl.knob} or its call — none was given`);
|
|
23
|
+
if (sec > SIGV4_PRESIGN_MAX_SEC) {
|
|
24
|
+
throw new Error(`object-store seat: ${op} was asked for a ${sec} s URL — a SigV4 presigned URL lives at most ${SIGV4_PRESIGN_MAX_SEC} s (7 days); ${ttl.knob} is refused above that when the configuration loads`);
|
|
25
|
+
}
|
|
26
|
+
return ttl.maxSec !== undefined ? Math.min(sec, ttl.maxSec) : sec;
|
|
27
|
+
}
|
|
2
28
|
function uriEncode(s, encodeSlash) {
|
|
3
29
|
let out = "";
|
|
4
30
|
for (const ch of Buffer.from(s, "utf8")) {
|
|
@@ -57,18 +83,21 @@ function presignCanonical(p) {
|
|
|
57
83
|
return `${url.origin}${canonicalUri}?${canonicalQuery}&X-Amz-Signature=${signature}`;
|
|
58
84
|
}
|
|
59
85
|
export function presignS3Url(p) {
|
|
86
|
+
assertRow(p.op, p.method, "signed");
|
|
87
|
+
const expiresSec = rowTtlSec(p.op, p.expiresSec);
|
|
60
88
|
if (p.key === "") {
|
|
61
89
|
throw new Error("presignS3Url: refusing to sign an empty key (single-object contract) — use presignS3BucketUrl for bucket-level operations");
|
|
62
90
|
}
|
|
63
91
|
if (p.key.startsWith("/") || p.key.split("/").some((seg) => seg === "." || seg === "..")) {
|
|
64
92
|
throw new Error(`presignS3Url: refusing to sign a key with a traversal segment: ${p.key}`);
|
|
65
93
|
}
|
|
66
|
-
return presignCanonical({ ...p, canonicalUri: `/${uriEncode(p.bucket, true)}/${uriEncode(p.key, false)}` });
|
|
94
|
+
return presignCanonical({ ...p, expiresSec, canonicalUri: `/${uriEncode(p.bucket, true)}/${uriEncode(p.key, false)}` });
|
|
67
95
|
}
|
|
68
96
|
export function presignS3BucketUrl(p) {
|
|
69
97
|
return presignCanonical({ ...p, canonicalUri: `/${uriEncode(p.bucket, true)}/` });
|
|
70
98
|
}
|
|
71
99
|
export function presignS3ListUrl(p) {
|
|
100
|
+
assertRow(p.op, "LIST", "signed");
|
|
72
101
|
return presignCanonical({
|
|
73
102
|
endpoint: p.endpoint,
|
|
74
103
|
canonicalUri: `/${uriEncode(p.bucket, true)}/`,
|
|
@@ -76,7 +105,7 @@ export function presignS3ListUrl(p) {
|
|
|
76
105
|
accessKey: p.accessKey,
|
|
77
106
|
secretKey: p.secretKey,
|
|
78
107
|
...(p.region ? { region: p.region } : {}),
|
|
79
|
-
|
|
108
|
+
expiresSec: rowTtlSec(p.op, p.expiresSec),
|
|
80
109
|
...(p.now ? { now: p.now } : {}),
|
|
81
110
|
extraQuery: {
|
|
82
111
|
"list-type": "2",
|
|
@@ -87,6 +116,7 @@ export function presignS3ListUrl(p) {
|
|
|
87
116
|
});
|
|
88
117
|
}
|
|
89
118
|
export function presignS3CopyUrl(p) {
|
|
119
|
+
assertRow(p.op, "COPY", "signed");
|
|
90
120
|
for (const [label, key] of [
|
|
91
121
|
["destination", p.key],
|
|
92
122
|
["source", p.sourceKey],
|
|
@@ -105,10 +135,14 @@ export function presignS3CopyUrl(p) {
|
|
|
105
135
|
accessKey: p.accessKey,
|
|
106
136
|
secretKey: p.secretKey,
|
|
107
137
|
...(p.region !== undefined ? { region: p.region } : {}),
|
|
108
|
-
|
|
138
|
+
expiresSec: rowTtlSec(p.op, p.expiresSec),
|
|
109
139
|
...(p.now !== undefined ? { now: p.now } : {}),
|
|
110
140
|
signedHeaders: { "x-amz-copy-source": copySource },
|
|
111
141
|
});
|
|
112
142
|
return { url, headers: { "x-amz-copy-source": copySource } };
|
|
113
143
|
}
|
|
144
|
+
export function buildPublicObjectUrl(p) {
|
|
145
|
+
assertRow(p.op, "GET", "anonymous");
|
|
146
|
+
return `${p.endpoint.replace(/\/+$/, "")}/${p.bucket}/${p.key.split("/").map(encodeURIComponent).join("/")}`;
|
|
147
|
+
}
|
|
114
148
|
//# sourceMappingURL=s3-presign.js.map
|
|
@@ -24,7 +24,7 @@ export type ScenarioPrefixRefusalReason = "stored_prefix" | "older_replica";
|
|
|
24
24
|
/**
|
|
25
25
|
* M42 的起服拒。具名类型 + 机读码 + 拒因;继承 {@link StoreBootRefusalError}(SQL 开库的等待窗不重试它;隐式 local 的降级臂不吞)。一个字节没改(扫描只读,标记没写)。
|
|
26
26
|
* · `stored_prefix` —— 存量里有以保留前缀开头的身份(`hits` 逐来源点名);
|
|
27
|
-
* · `older_replica` ——
|
|
27
|
+
* · `older_replica` —— 标记不在,而有停-迁-起证据(守卫段在扫描之前判):更早版本的副本可能还在服务,扫描之后它还会收下这类身份 ⇒ 全停之后再起(`live` = 证据,带时刻)。
|
|
28
28
|
*/
|
|
29
29
|
export declare class ScenarioPrefixSwitchRefusedError extends StoreBootRefusalError {
|
|
30
30
|
readonly reason: ScenarioPrefixRefusalReason;
|
|
@@ -31,9 +31,9 @@ export class ScenarioPrefixSwitchRefusedError extends StoreBootRefusalError {
|
|
|
31
31
|
case "older_replica":
|
|
32
32
|
if (live === undefined)
|
|
33
33
|
throw new Error("scenario-prefix-switch: an older_replica refusal carries its evidence");
|
|
34
|
-
return (`${SCENARIO_PREFIX_SWITCH_REFUSED_CODE}:
|
|
34
|
+
return (`${SCENARIO_PREFIX_SWITCH_REFUSED_CODE}: this version reserves the prefix "${SCENARIO_SUBJECT_PREFIX}" and checks stored identities for it once before recording a marker, but ${olderReplicaEvidenceSentence(live)} ` +
|
|
35
35
|
`— a replica of an earlier version may still be serving, and it accepts principals with that prefix, so a clean check now would not stay clean. ` +
|
|
36
|
-
`Nothing was changed and no marker was written. ${stopThenStartAction(live.after)}`);
|
|
36
|
+
`Nothing was scanned or changed and no marker was written. ${stopThenStartAction(live.after)}`);
|
|
37
37
|
default: {
|
|
38
38
|
const unhandled = reason;
|
|
39
39
|
throw new Error(`scenario-prefix-switch: unknown refusal reason ${String(unhandled)}`);
|
|
@@ -47,8 +47,8 @@ export interface SchedulerStoreLog {
|
|
|
47
47
|
* 的 `record` 可能是任意内容 —— 只报下标):
|
|
48
48
|
* · `unreadable-file` ⇒ warn(整份文件不是 JSON 数组:读成零条,写者一律不写 —— 见 `mutateSchedulerStore`);
|
|
49
49
|
* · `malformed-record` ⇒ warn(这一条读不懂、被跳过;下一个写者落盘时它就没了);
|
|
50
|
-
* · `stale-session-record` ⇒ info(会话链上过期 ≥ 7 天的记录,读时丢、下一个写者落盘)
|
|
51
|
-
*
|
|
50
|
+
* · `stale-session-record` ⇒ info(会话链上过期 ≥ 7 天的记录,读时丢、下一个写者落盘)。
|
|
51
|
+
* (settings-schema 26.0.0 删了调度店的读时重铸一步与它的收据臂:仍按会话链键存的 durable 记录逐字读出、不告警 —— 没有日志可写。)
|
|
52
52
|
*/
|
|
53
53
|
export declare function logSchedulerWarnings(log: SchedulerStoreLog, path: string, warnings: readonly SchedulerParseWarning[]): void;
|
|
54
54
|
/**
|
|
@@ -75,9 +75,6 @@ export function logSchedulerWarnings(log, path, warnings) {
|
|
|
75
75
|
case "stale-session-record":
|
|
76
76
|
log.info("scheduler_store_record_stale", { path, index: w.index, id: w.id, note: "a session-chained record whose next run is ≥ 7 days past — dropped on read (the next write persists the drop)" });
|
|
77
77
|
break;
|
|
78
|
-
case "one-time-migration":
|
|
79
|
-
log.info("scheduler_store_record_migrated", { path, index: w.index, migration: w.receipt.migration, appliedAs: w.receipt.appliedAs, note: "settings-schema one-time migration rewrote this record on read (the next write persists it)" });
|
|
80
|
-
break;
|
|
81
78
|
default: {
|
|
82
79
|
const unhandled = w;
|
|
83
80
|
throw new Error(`scheduler store: unknown read warning ${JSON.stringify(unhandled)}`);
|
|
@@ -185,8 +185,10 @@ export declare function describeMismatchedTables(dialect: SqlDialect, mismatches
|
|
|
185
185
|
/**
|
|
186
186
|
* **升级清单**(多行;`[]` = 没有语句要部署者执行,清单不出):一次起服的拒句里「这只库此刻对本构建还差什么、先后顺序」一段。
|
|
187
187
|
* 缺列拒、判活拒、一次性迁移的拒本来各报各的一段 —— 运维补一句再起、才撞上下一族(列册对账在迁移段之后时,第四次起服才拒出其余全部 ALTER)。
|
|
188
|
-
*
|
|
189
|
-
*
|
|
188
|
+
* 清单把本构建对这一只库的全部动作写成一张:⓪ 这只库要求、本构建没有的能力(起服要求表 `serving_requirement` 里本构建能力名单之外的行;有才出,排在一切语句之前 ——
|
|
189
|
+
* 照清单补完语句也不会让本构建能在这里服务:库形对账与「谁可以服务」是两个事实,补列是在把那条迁移改掉的形补回去)① 逐表的 ALTER(其下 {@link describeMismatchedTables} 的逐表段,
|
|
190
|
+
* 全库一次列全)② 这只库**还欠**的停-迁-起迁移 ③ 起服。第 ⓪ 步与准入同一只读法(`serving-requirement.ts` 的 `unmetServingRequirements`);要求表不在 ⇒ 不出(那是准入的 `table_absent`,
|
|
191
|
+
* 清单不判);读抛 ⇒ 照出并如实说没读到。第 ② 步逐行问登记行的 `stopThenStart.owedOn`(一次性迁移文件静态依赖本文件,所以惰性载入)—— 那条迁移的守卫段自己问的同一只判据,清单不另判:
|
|
190
192
|
* 已经走过它们的库(标记落了 / 部署格已搬 / 零行旧词)一条不欠 ⇒ 第 ② 步与它的「不可滚动」动作段都不出,起服是第 ② 步。某一条读不出欠不欠(探针读抛)⇒ 照列并如实说
|
|
191
193
|
* 没读到(多停一次,不漏停)。`read` = 列册对账读列册的同一只无参读口。
|
|
192
194
|
*/
|
|
@@ -2,7 +2,9 @@ import { recordEnsureStatements } from "./schema-ensure-legs.js";
|
|
|
2
2
|
import { readLiveColumns } from "./schema-live-columns.js";
|
|
3
3
|
import { SCHEMA_MISMATCH_WAYS_OUT } from "./schema-drift-sentence.js";
|
|
4
4
|
import { SCHEMA_MISMATCH_ERROR_CODE, SchemaMismatchRefusedError, StoreBootRefusalError } from "./store-contracts.js";
|
|
5
|
-
import { stopThenStartAction } from "./stop-then-start-sentence.js";
|
|
5
|
+
import { stopThenStartAction, unmetRequirementChecklistStep } from "./stop-then-start-sentence.js";
|
|
6
|
+
import { SERVING_REQUIREMENT_TABLE, unmetServingRequirements } from "./serving-requirement.js";
|
|
7
|
+
import { REPLICA_CAPABILITIES } from "./replica-registration.js";
|
|
6
8
|
const QUOTES = new Set(["'", '"', "`"]);
|
|
7
9
|
function stripComments(sql) {
|
|
8
10
|
let out = "";
|
|
@@ -469,7 +471,11 @@ export async function describeUpgradeChecklist(read, dialect, mismatches) {
|
|
|
469
471
|
if (owes)
|
|
470
472
|
owed.push(` - ${m.id}: ${m.reason}`);
|
|
471
473
|
}
|
|
472
|
-
const steps = [
|
|
474
|
+
const steps = [];
|
|
475
|
+
const requirements = await unmetRequirementsForChecklist(read, dialect);
|
|
476
|
+
if (requirements !== undefined)
|
|
477
|
+
steps.push(requirements);
|
|
478
|
+
steps.push(["Run every statement printed below, each recipe in the order it is printed (a printed comment line marks a value only you can choose) — all tables at once, before anything else (this build never alters a database for you)."]);
|
|
473
479
|
if (owed.length > 0) {
|
|
474
480
|
steps.push([
|
|
475
481
|
"Stop-then-start one-time migrations this database still owes: this build runs them itself on its first boot (no statement from you), and each refuses to start — writing nothing — while a run on this database has",
|
|
@@ -484,6 +490,17 @@ export async function describeUpgradeChecklist(read, dialect, mismatches) {
|
|
|
484
490
|
...steps.flatMap((lines, i) => lines.map((l, k) => (k === 0 ? ` ${i + 1}. ${l}` : ` ${l}`))),
|
|
485
491
|
];
|
|
486
492
|
}
|
|
493
|
+
async function unmetRequirementsForChecklist(read, dialect) {
|
|
494
|
+
try {
|
|
495
|
+
if (!(await readLiveColumns(read, dialect)).has(SERVING_REQUIREMENT_TABLE))
|
|
496
|
+
return undefined;
|
|
497
|
+
const unmet = await unmetServingRequirements(read, { capabilities: REPLICA_CAPABILITIES });
|
|
498
|
+
return unmet.length === 0 ? undefined : unmetRequirementChecklistStep(unmet);
|
|
499
|
+
}
|
|
500
|
+
catch (err) {
|
|
501
|
+
return unmetRequirementChecklistStep([], err instanceof Error ? err.message : String(err));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
487
504
|
export function describeSchemaMismatch(dialect, mismatches, checklist = []) {
|
|
488
505
|
const lines = [
|
|
489
506
|
`${SCHEMA_MISMATCH_ERROR_CODE}: the ${dialect === "pg" ? "PostgreSQL" : "MySQL-protocol"} database does not match this build's schema — refusing to start.`,
|
|
@@ -20,6 +20,8 @@ export const CENTRAL_SCHEMA_INDEXES = [
|
|
|
20
20
|
{ table: "file_history_boundary_file", name: "idx_file_history_bf_key", columns: ["scope", "key_hash"] },
|
|
21
21
|
{ table: "file_history_boundary", name: "uq_file_history_boundary_seq", columns: ["scope", "publish_seq"], unique: true },
|
|
22
22
|
{ table: "file_history_blob", name: "idx_file_history_blob_created", columns: ["created_at"] },
|
|
23
|
+
{ table: "file_history_blob_grant", name: "idx_file_history_blob_grant_granted", columns: ["granted_at"] },
|
|
24
|
+
{ table: "file_history_blob_grant", name: "idx_file_history_blob_grant_blob", columns: ["blob_hash"] },
|
|
23
25
|
{ table: "workflow_run", name: "idx_wfrun_scope_created", columns: ["scope", "created_at_ms"] },
|
|
24
26
|
{ table: "workflow_run", name: "idx_wfrun_scope_status", columns: ["scope", "status"] },
|
|
25
27
|
{ table: "workflow_agent_session", name: "idx_wfagentsess_run", columns: ["run_id"] },
|
|
@@ -55,8 +55,8 @@ export declare class FileSendFileLedger implements SendFileLedger {
|
|
|
55
55
|
}
|
|
56
56
|
export interface LedgerRecordingDeps {
|
|
57
57
|
ledger: SendFileLedger;
|
|
58
|
-
/** Best-effort reclaim of the uploaded object when the record fails (issuer.deleteObject). */
|
|
59
|
-
deleteObject: (bucket: string, key: string) => Promise<void>;
|
|
58
|
+
/** Best-effort reclaim of the uploaded object when the record fails (issuer.deleteObject; `track` = the link's track). */
|
|
59
|
+
deleteObject: (bucket: string, key: string, track: IssuedFileLink["track"]) => Promise<void>;
|
|
60
60
|
warn?: (msg: string, meta?: Record<string, unknown>) => void;
|
|
61
61
|
now?: () => number;
|
|
62
62
|
newId?: () => string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { AppendLog, ensureDir, uuidv7 } from "@sema-agent/core";
|
|
3
3
|
import { replayJsonlSkipping } from "../observability/corrupt-read-seat.js";
|
|
4
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
4
5
|
export const SENDFILE_SINGLE_USER_SCOPE = "_";
|
|
5
6
|
export class TiDBSendFileLedger {
|
|
6
7
|
pool;
|
|
@@ -17,6 +18,7 @@ export class TiDBSendFileLedger {
|
|
|
17
18
|
return rows.map((r) => rowToEntry(r));
|
|
18
19
|
}
|
|
19
20
|
}
|
|
21
|
+
sealStoreClass(TiDBSendFileLedger, "tidb-send-file-ledger", { record: "exit", listByScope: "exit" });
|
|
20
22
|
export class PgSendFileLedger {
|
|
21
23
|
pool;
|
|
22
24
|
constructor(pool) {
|
|
@@ -32,6 +34,7 @@ export class PgSendFileLedger {
|
|
|
32
34
|
return res.rows.map(rowToEntry);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
37
|
+
sealStoreClass(PgSendFileLedger, "pg-send-file-ledger", { record: "exit", listByScope: "exit" });
|
|
35
38
|
function rowToEntry(r) {
|
|
36
39
|
return {
|
|
37
40
|
id: String(r.id),
|
|
@@ -127,10 +130,10 @@ export function withLedgerRecording(send, deps) {
|
|
|
127
130
|
let reclaimed = true;
|
|
128
131
|
try {
|
|
129
132
|
try {
|
|
130
|
-
await deps.deleteObject(link.bucket, link.key);
|
|
133
|
+
await deps.deleteObject(link.bucket, link.key, link.track);
|
|
131
134
|
}
|
|
132
135
|
catch {
|
|
133
|
-
await deps.deleteObject(link.bucket, link.key);
|
|
136
|
+
await deps.deleteObject(link.bucket, link.key, link.track);
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
catch (de) {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** SigV4 physical ceiling (AWS: X-Amz-Expires max 604800s = 7 days). */
|
|
2
|
-
export declare const PRESIGN_MAX_TTL_SEC = 604800;
|
|
3
1
|
/**
|
|
4
2
|
* Multi-tenant governance (clay ruling 2026-07-14, blackboard [ref]② variant a with a HASHED segment): every
|
|
5
3
|
* object key carries a per-tenant SCOPE SEGMENT so tenants can be listed/revoked by prefix on the store itself,
|
|
@@ -102,8 +100,9 @@ export interface SendUserFileIssuer {
|
|
|
102
100
|
* semantics as issue() — prepare and finalize share ONE key, so the segment is fixed at prepare time. */
|
|
103
101
|
prepareDirectUpload(filename: string | undefined, ttlSec?: number, scope?: string): PreparedDirectUpload;
|
|
104
102
|
/** Best-effort object reclaim (ledger fail-loud path: an uploaded object whose ledger record failed would be
|
|
105
|
-
* an unmanageable orphan — delete it). Signed DELETE against the INTERNAL endpoint with adapter creds.
|
|
106
|
-
|
|
103
|
+
* an unmanageable orphan — delete it). Signed DELETE against the INTERNAL endpoint with adapter creds. `track` = the link's track
|
|
104
|
+
* (which object-store action row the delete is: the permanent track's bucket or the private one). */
|
|
105
|
+
deleteObject(bucket: string, key: string, track: IssuedFileLink["track"]): Promise<void>;
|
|
107
106
|
/** The public endpoint web clients need for rendering context (bootstrap/capabilities透出). */
|
|
108
107
|
readonly publicEndpoint: string | undefined;
|
|
109
108
|
}
|