@sema-agent/server 7.43.0 → 7.44.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/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { PgWriteBehindCounter } from "./write-behind-counter.js";
|
|
2
|
-
/** The counter's table binding for the cumulative cost quota (mirror of the TiDB twin's binding). */
|
|
3
2
|
const COST_QUOTA_TABLE = { table: "cost_quota", keyCol: "scope_key", valCol: "micro_usd" };
|
|
4
3
|
export class PgCostQuota {
|
|
5
4
|
counter;
|
|
6
|
-
/** #322:与 TiDB 孪生逐字同语义(限额=比较参数;关断哨兵零 SQL;窗长换代=换桶)。 */
|
|
7
5
|
limitMicroUsd;
|
|
8
6
|
refreshRequested = false;
|
|
9
7
|
refreshIntervalMs;
|
|
@@ -36,7 +34,6 @@ export class PgCostQuota {
|
|
|
36
34
|
return;
|
|
37
35
|
this.counter.addLocal(scopeKey, micro);
|
|
38
36
|
}
|
|
39
|
-
// write-behind lifecycle (delegated; exposed for the reaper/tests)
|
|
40
37
|
flush() {
|
|
41
38
|
return this.counter.flush();
|
|
42
39
|
}
|
|
@@ -57,9 +54,6 @@ export class PgCostQuota {
|
|
|
57
54
|
this.counter.stop();
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
|
-
/** PG DDL for the `cost_quota` table (translated from tidb-pool.ts SCHEMA_STATEMENTS: BIGINT same,
|
|
61
|
-
* DATETIME(3)→TIMESTAMPTZ(3), inline `KEY idx_window`→separate CREATE INDEX). DISJOINT from other stores'
|
|
62
|
-
* tables, so a self-contained ensureSchema is safe (the central pg-pool aggregation is done separately). */
|
|
63
57
|
export const PG_COST_QUOTA_SCHEMA = [
|
|
64
58
|
`CREATE TABLE IF NOT EXISTS cost_quota (
|
|
65
59
|
scope_key VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -70,7 +64,6 @@ export const PG_COST_QUOTA_SCHEMA = [
|
|
|
70
64
|
)`,
|
|
71
65
|
`CREATE INDEX IF NOT EXISTS idx_cost_quota_window ON cost_quota (window_bucket)`,
|
|
72
66
|
];
|
|
73
|
-
/** Idempotent schema apply for the cost_quota table (the PG twin of tidb-pool.ts ensureSchema). */
|
|
74
67
|
export async function ensureSchema(pool) {
|
|
75
68
|
for (const stmt of PG_COST_QUOTA_SCHEMA)
|
|
76
69
|
await pool.query(stmt);
|
package/dist/plugins/pg-pool.js
CHANGED
|
@@ -1,32 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PostgreSQL pool + central schema — the PG sibling of tidb-pool.ts, for the second run-store backend
|
|
3
|
-
* (clay 2026-06-21). Schema ownership is CENTRAL (one ensurePgSchema, like tidb-pool's SCHEMA_STATEMENTS) — PG
|
|
4
|
-
* stores assume the tables exist and NEVER create their own (a per-store `CREATE TABLE IF NOT EXISTS` is
|
|
5
|
-
* first-writer-wins, so a trimmed table would shadow the full one and drop columns).
|
|
6
|
-
*
|
|
7
|
-
* Dialect deltas vs the MySQL DDL in tidb-pool.ts: JSON→JSONB, DATETIME(3)→TIMESTAMPTZ(3), TINYINT(1)→SMALLINT,
|
|
8
|
-
* inline `KEY …`→separate `CREATE INDEX`. checkpoint timestamps stay epoch-ms BIGINT (core's Checkpoint uses ms),
|
|
9
|
-
* matching the TiDB schema byte-for-byte semantically. Only the tables PG backends implement so far are listed
|
|
10
|
-
* (run-store + checkpoint); the remaining tidb-* tables are added as their PG stores land (tracked).
|
|
11
|
-
*
|
|
12
|
-
* ─────────────────────────────── SCHEMA POLICY (clay 裁 2026-07-26) ───────────────────────────────
|
|
13
|
-
* THIS CODE IS THE SINGLE SOURCE OF TRUTH for the PG schema. The stack is not yet in production and runs
|
|
14
|
-
* against a single local operator's database, so a schema change is DROP-AND-RECREATE (drop the database,
|
|
15
|
-
* boot, `ensurePgSchema` rebuilds it) — NOT an in-place migration.
|
|
16
|
-
*
|
|
17
|
-
* Consequence, and it is a hard rule: **do NOT add new `ALTER TABLE` seams here.** Every column / default /
|
|
18
|
-
* constraint change is folded into its own `CREATE TABLE`, and this array stays pure `CREATE TABLE` +
|
|
19
|
-
* `CREATE INDEX`. The historical additive-ALTER seams were folded in on 2026-07-26 (they had all decayed
|
|
20
|
-
* into permanent no-ops — the CREATEs already carried the columns).
|
|
21
|
-
*
|
|
22
|
-
* Because the seams are gone, the semantics they used to document now live as inline `--` comments ON THE
|
|
23
|
-
* COLUMN inside the CREATE, not as TypeScript comments outside the template literal: the full-set SQL
|
|
24
|
-
* baseline `docs/schema/baseline-pg.sql` is GENERATED from these statement strings, so only what is inside
|
|
25
|
-
* the SQL survives the export. The baseline is a derived artifact — regenerate it, never hand-edit it.
|
|
26
|
-
*/
|
|
27
1
|
import pg from "pg";
|
|
28
|
-
// Each PG store owns its own (disjoint) tables' DDL via a standalone idempotent ensureSchema; the central apply
|
|
29
|
-
// composes them so production wires ONE ensurePgSchema (the PG twin of tidb-pool's single ensureSchema).
|
|
30
2
|
import { ensureSchema as ensureSessionSchema } from "./pg-session-storage.js";
|
|
31
3
|
import { ensureSchema as ensureToolResultSchema } from "./tool-result-store-sql.js";
|
|
32
4
|
import { ensureSchema as ensureCostQuotaSchema } from "./pg-cost-quota.js";
|
|
@@ -87,7 +59,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
87
59
|
PRIMARY KEY (session_id)
|
|
88
60
|
)`,
|
|
89
61
|
`CREATE INDEX IF NOT EXISTS idx_task_active_task ON task_active (task_id)`,
|
|
90
|
-
// Durable-checkpoint (core 1.67 / design/45) — the FULL table (matches tidb-pool.ts checkpoint + its migrations).
|
|
91
62
|
`CREATE TABLE IF NOT EXISTS checkpoint (
|
|
92
63
|
token VARCHAR(120) COLLATE "C" NOT NULL,
|
|
93
64
|
scope VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -128,7 +99,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
128
99
|
updated_at_ms BIGINT NOT NULL,
|
|
129
100
|
PRIMARY KEY (session_id)
|
|
130
101
|
)`,
|
|
131
|
-
// E18 resume-at anchor map (the PG twin of the TiDB resume_anchor table — eventId→entryId; see tidb-pool.ts).
|
|
132
102
|
`CREATE TABLE IF NOT EXISTS resume_anchor (
|
|
133
103
|
session_id VARCHAR(64) COLLATE "C" NOT NULL,
|
|
134
104
|
event_id VARCHAR(64) COLLATE "C" NOT NULL,
|
|
@@ -138,8 +108,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
138
108
|
PRIMARY KEY (session_id, event_id)
|
|
139
109
|
)`,
|
|
140
110
|
`CREATE INDEX IF NOT EXISTS idx_resume_anchor_session ON resume_anchor (session_id)`,
|
|
141
|
-
// Per-session per-toolName approval exemption (the PG twin — see tidb-pool.ts /
|
|
142
|
-
// sema-internal server/docs/design/APPROVAL-SESSION-EXEMPTION.md).
|
|
143
111
|
`CREATE TABLE IF NOT EXISTS approval_exemption (
|
|
144
112
|
session_id VARCHAR(64) COLLATE "C" NOT NULL,
|
|
145
113
|
tool_name VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -147,9 +115,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
147
115
|
created_at TIMESTAMPTZ(3) NOT NULL,
|
|
148
116
|
PRIMARY KEY (session_id, tool_name)
|
|
149
117
|
)`,
|
|
150
|
-
// SendUserFile server-side ledger (the PG twin — scope↔object mapping for per-tenant list/revoke; the hashed
|
|
151
|
-
// key segment hides this from URLs. id = uuidv7 time-ordered PK = keyset cursor; see tidb-pool.ts /
|
|
152
|
-
// send-file-ledger.ts).
|
|
153
118
|
`CREATE TABLE IF NOT EXISTS sendfile_link (
|
|
154
119
|
id VARCHAR(64) COLLATE "C" NOT NULL,
|
|
155
120
|
scope VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -165,9 +130,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
165
130
|
PRIMARY KEY (id)
|
|
166
131
|
)`,
|
|
167
132
|
`CREATE INDEX IF NOT EXISTS idx_sendfile_link_scope ON sendfile_link (scope, id)`,
|
|
168
|
-
// E6 durable SessionPolicyStore (the PG twin of the TiDB session_policy table; policy_key = sha256(JSON.stringify(
|
|
169
|
-
// [sessionId, principal ?? null])) = a fixed 64-char hash PK; rules JSONB; CAS-versioned tighten-only — see
|
|
170
|
-
// tidb-pool.ts / session-policy-store-sql.ts).
|
|
171
133
|
`CREATE TABLE IF NOT EXISTS session_policy (
|
|
172
134
|
policy_key CHAR(64) COLLATE "C" NOT NULL,
|
|
173
135
|
session_id VARCHAR(64) COLLATE "C" NOT NULL,
|
|
@@ -182,8 +144,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
182
144
|
PRIMARY KEY (policy_key)
|
|
183
145
|
)`,
|
|
184
146
|
`CREATE INDEX IF NOT EXISTS idx_session_policy_session ON session_policy (session_id)`,
|
|
185
|
-
// E19 rewind-files (the PG twin of the TiDB snapshot_manifest/snapshot_blob; relPath→blob_hash manifest +
|
|
186
|
-
// content-addressed BYTEA blobs; core captureManifest/applyManifest do the walk/restore — see tidb-pool.ts).
|
|
187
147
|
`CREATE TABLE IF NOT EXISTS snapshot_manifest (
|
|
188
148
|
scope VARCHAR(64) COLLATE "C" NOT NULL,
|
|
189
149
|
snap_key VARCHAR(64) COLLATE "C" NOT NULL,
|
|
@@ -205,10 +165,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
205
165
|
created_at TIMESTAMPTZ(3) NOT NULL
|
|
206
166
|
)`,
|
|
207
167
|
`CREATE INDEX IF NOT EXISTS idx_snapshot_blob_created ON snapshot_blob (created_at)`,
|
|
208
|
-
// SVC-2 (core CORE-7) durable WorkflowJournalStore — the PG twin of the TiDB workflow_journal table (cross-replica
|
|
209
|
-
// resume journal; (run_id, ordinal) PK = idempotent OVERWRITE upsert; `result` = JSON.stringify(TaskResult)). `result`
|
|
210
|
-
// is TEXT, NOT JSONB — the byte-match contract is "string in, string out" (the store JSON.parses on load); JSONB would
|
|
211
|
-
// make `pg` auto-parse the row back to an object and break the twin's String()→JSON.parse path. See workflow-journal-store-sql.ts.
|
|
212
168
|
`CREATE TABLE IF NOT EXISTS workflow_journal (
|
|
213
169
|
run_id VARCHAR(191) COLLATE "C" NOT NULL,
|
|
214
170
|
ordinal INT NOT NULL,
|
|
@@ -223,8 +179,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
223
179
|
created_at_ms BIGINT NOT NULL,
|
|
224
180
|
PRIMARY KEY (run_id, ordinal)
|
|
225
181
|
)`,
|
|
226
|
-
// RB-242 / WF2 ([1981] core 拍板 a 形):cross-replica workflow resume admission lease — the PG twin of
|
|
227
|
-
// workflow_resume_claim in tidb-pool.ts (rationale there; TTL = crash backstop only).
|
|
228
182
|
`CREATE TABLE IF NOT EXISTS workflow_resume_claim (
|
|
229
183
|
source_run_id VARCHAR(191) COLLATE "C" NOT NULL,
|
|
230
184
|
scope VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -232,8 +186,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
232
186
|
claimed_at_ms BIGINT NOT NULL,
|
|
233
187
|
PRIMARY KEY (source_run_id, scope)
|
|
234
188
|
)`,
|
|
235
|
-
// P1 (fleet failover): WorkflowRunStore + completion-inbox PG twins (design doc in workflow-run-store-sql.ts).
|
|
236
|
-
// `run` is TEXT not jsonb (node-pg auto-parse would break the shared String()→JSON.parse path).
|
|
237
189
|
`CREATE TABLE IF NOT EXISTS workflow_run (
|
|
238
190
|
id VARCHAR(191) COLLATE "C" NOT NULL,
|
|
239
191
|
scope VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -279,7 +231,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
279
231
|
PRIMARY KEY (session_id, kind, run_id)
|
|
280
232
|
)`,
|
|
281
233
|
`CREATE INDEX IF NOT EXISTS idx_wffence_until ON workflow_inbox_fence (until_ms)`,
|
|
282
|
-
// 1.108 review fix (lens③ HIGH): notify-journal PG twin (design note in tidb-pool.ts).
|
|
283
234
|
`CREATE TABLE IF NOT EXISTS workflow_notify_journal (
|
|
284
235
|
run_id VARCHAR(191) COLLATE "C" NOT NULL,
|
|
285
236
|
scope VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -291,10 +242,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
291
242
|
PRIMARY KEY (run_id)
|
|
292
243
|
)`,
|
|
293
244
|
`CREATE INDEX IF NOT EXISTS idx_wfnotify_acked ON workflow_notify_journal (acked)`,
|
|
294
|
-
// design/177 shared-memory store —— org 盘三张表的 PG twin(MySQL 侧的逐列注释见 tidb-pool.ts;方言差
|
|
295
|
-
// 只在 TINYINT(1)→SMALLINT 与 inline KEY→独立 CREATE INDEX)。🔴 与 `agent_memory_engine_*` 零关系。
|
|
296
|
-
// 每个字符串列都带 COLLATE "C":core 的 cursor 词表是「UTF-16 code-unit 序」,而它的翻页只在
|
|
297
|
-
// `nextCursor > windowCursor`(JS 比较)成立时才继续 —— 数据库若按 locale 排序,一次列举会静默截断。
|
|
298
245
|
`CREATE TABLE IF NOT EXISTS shared_memory_scope (
|
|
299
246
|
scope_key VARCHAR(190) COLLATE "C" NOT NULL,
|
|
300
247
|
state VARCHAR(16) COLLATE "C" NOT NULL,
|
|
@@ -321,17 +268,6 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
321
268
|
PRIMARY KEY (store_id, path)
|
|
322
269
|
)`,
|
|
323
270
|
];
|
|
324
|
-
/** Build the pg PoolConfig from PG config (pure → unit-testable apart from the live connection) — the PG twin of
|
|
325
|
-
* tidbPoolOptions. `dbQueryTimeoutMs` (DB_QUERY_TIMEOUT_MS, S9 deeper fix) arms a POOL-WIDE per-query ceiling on
|
|
326
|
-
* every client the pool hands out, BOTH sides:
|
|
327
|
-
* - `statement_timeout` = T: SERVER-side cancel (sent as a startup parameter) — frees the server's resources
|
|
328
|
-
* and surfaces the canonical 57014 error on any statement that runs past T;
|
|
329
|
-
* - `query_timeout` = T + 5s: CLIENT-side read-timeout backstop for the cases the server can't answer at all
|
|
330
|
-
* (dead network / hung server — the S9 hang class). Slightly ABOVE statement_timeout on purpose, so the
|
|
331
|
-
* server's clean cancel normally wins and the client timer only fires when no response ever arrives (a
|
|
332
|
-
* query_timeout rejection makes pg-pool DESTROY that client, discarding the poisoned connection).
|
|
333
|
-
* Unset = both off (byte-compat: legit heavyweight statements — boot DDL, ≤64 MiB snapshot-blob rows — make a
|
|
334
|
-
* universal default unsafe; the S9 write-behind counter face carries its own always-on per-query timeout). */
|
|
335
271
|
export function pgPoolOptions(pgCfg, dbQueryTimeoutMs) {
|
|
336
272
|
return {
|
|
337
273
|
host: pgCfg.host,
|
|
@@ -343,32 +279,14 @@ export function pgPoolOptions(pgCfg, dbQueryTimeoutMs) {
|
|
|
343
279
|
...(dbQueryTimeoutMs ? { statement_timeout: dbQueryTimeoutMs, query_timeout: dbQueryTimeoutMs + 5_000 } : {}),
|
|
344
280
|
};
|
|
345
281
|
}
|
|
346
|
-
/** Create the PG pool from a connection string (or pg.PoolConfig). Thin — production backend-selection wiring
|
|
347
|
-
* (a ServiceConfig.pg sibling of .tidb) is a tracked follow-on. */
|
|
348
282
|
export function createPgPool(opts) {
|
|
349
283
|
return typeof opts === "string" ? new pg.Pool({ connectionString: opts }) : new pg.Pool(opts);
|
|
350
284
|
}
|
|
351
|
-
/** A fixed bigint key for the `pg_advisory_lock` that serializes the whole `ensurePgSchema` DDL run (see below).
|
|
352
|
-
* Arbitrary constant; only its uniqueness within this app matters (advisory-lock keys are app-private). */
|
|
353
285
|
const ENSURE_SCHEMA_LOCK_KEY = 4906;
|
|
354
|
-
/** Idempotent central schema apply (the PG twin of tidb-pool.ts ensureSchema): the run/checkpoint tables here +
|
|
355
|
-
* every PG store's own (disjoint) tables. Order is irrelevant (CREATE IF NOT EXISTS, no cross-table FKs).
|
|
356
|
-
*
|
|
357
|
-
* Concurrency: callers run this concurrently — tests fan ALL integration suites out in parallel (each beforeAll
|
|
358
|
-
* calls ensurePgSchema), and in production every replica calls it at boot. Concurrent DDL on the SAME table makes
|
|
359
|
-
* PG raise `tuple concurrently updated` in its catalog. We serialize the entire run behind a session-level
|
|
360
|
-
* `pg_advisory_lock`: the first caller does the real CREATE/ALTER, the rest block until it unlocks then find every
|
|
361
|
-
* statement already satisfied (IF NOT EXISTS ⇒ no-op), so there is no catalog race. The DDL semantics are
|
|
362
|
-
* unchanged — only its timing is serialized. The advisory lock is SESSION (connection)-level, so the lock and
|
|
363
|
-
* ALL the DDL MUST run on the one client we hold; routing DDL through `pool.query` could land on a different
|
|
364
|
-
* pooled connection and silently void the lock. */
|
|
365
286
|
export async function ensurePgSchema(pool) {
|
|
366
287
|
const client = await pool.connect();
|
|
367
288
|
let locked = false;
|
|
368
289
|
try {
|
|
369
|
-
// pg_advisory_lock blocks until the lock is granted (the DDL run is short, so blocking is acceptable). If the
|
|
370
|
-
// lock op itself errors we DEGRADE to running the DDL unserialized rather than failing boot — the CREATE IF NOT
|
|
371
|
-
// EXISTS statements are still individually idempotent (they just lose the cross-caller serialization).
|
|
372
290
|
try {
|
|
373
291
|
await client.query("SELECT pg_advisory_lock($1)", [ENSURE_SCHEMA_LOCK_KEY]);
|
|
374
292
|
locked = true;
|
|
@@ -386,20 +304,10 @@ export async function ensurePgSchema(pool) {
|
|
|
386
304
|
await ensureOutcomeLedgerSchema(client);
|
|
387
305
|
await ensureImageIndexSchema(client);
|
|
388
306
|
await ensureImageBakeSchema(client);
|
|
389
|
-
// #151 流内审批协议持久层(MySQL twin 走 tidb-pool 的 SCHEMA_STATEMENTS 展开)。该 ensure 收的是裸
|
|
390
|
-
// `PgQueryFn`(而非兄弟们收的 client 形),故在这里绑一层 —— DDL 仍然跑在**同一条** client 上,
|
|
391
|
-
// advisory lock 的 session 语义不受影响(见本函数头注:路由到别的池连接会静默作废那把锁)。
|
|
392
307
|
await ensurePgApprovalAskSchema((text, params) => client.query(text, params));
|
|
393
|
-
// design/183 form b 的 SQL 收编日志(MySQL twin 走 tidb-pool 的 SCHEMA_STATEMENTS 展开)。
|
|
394
|
-
// 同 approval-ask:收裸 query 形,故在这里绑一层——DDL 仍跑在**同一条** client 上,advisory lock 不失效。
|
|
395
308
|
await ensurePgAdoptionLogSchema((text, params) => client.query(text, params));
|
|
396
|
-
// #154 车二:持久化权限规则店三张表(MySQL twin 走 tidb-pool 的 SCHEMA_STATEMENTS 展开)。
|
|
397
|
-
// 同上一行的绑法 —— DDL 跑在**同一条** client 上,advisory lock 的 session 语义不受影响。
|
|
398
309
|
await ensurePgPermissionRuleSchema((text, params) => client.query(text, params));
|
|
399
|
-
// #193 车4 件1:durable leader-run 登记表(MySQL twin 走 tidb-pool 的 SCHEMA_STATEMENTS 展开)。同上绑法。
|
|
400
310
|
await ensurePgLeaderRunSchema((text, params) => client.query(text, params));
|
|
401
|
-
// #270 车1:托管留存执行面四表(审计/hold/sweep 租约/墓碑;MySQL twin 走 tidb-pool 的 SCHEMA_STATEMENTS
|
|
402
|
-
// 展开)。同上绑法 —— DDL 跑在**同一条** client 上,advisory lock 的 session 语义不受影响。
|
|
403
311
|
await ensurePgRetentionSchema((text, params) => client.query(text, params));
|
|
404
312
|
}
|
|
405
313
|
finally {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { PgWriteBehindCounter } from "./write-behind-counter.js";
|
|
2
|
-
/** The counter's table binding for the per-key request rate limit (mirror of the TiDB twin's binding). */
|
|
3
2
|
const RATE_LIMIT_TABLE = { table: "rate_limit", keyCol: "limit_key", valCol: "hits" };
|
|
4
3
|
export class PgRateLimiter {
|
|
5
4
|
counter;
|
|
6
|
-
/** #322:与 TiDB 孪生逐字同语义(限额=比较参数;关断哨兵停/起刷新环)。 */
|
|
7
5
|
limit;
|
|
8
6
|
refreshRequested = false;
|
|
9
7
|
refreshIntervalMs;
|
|
@@ -26,17 +24,14 @@ export class PgRateLimiter {
|
|
|
26
24
|
check(key) {
|
|
27
25
|
if (this.limit <= 0)
|
|
28
26
|
return { allowed: true, retryAfterSec: 0, remaining: Number.POSITIVE_INFINITY };
|
|
29
|
-
const usedBefore = this.counter.used(key);
|
|
30
|
-
this.counter.addLocal(key, 1);
|
|
27
|
+
const usedBefore = this.counter.used(key);
|
|
28
|
+
this.counter.addLocal(key, 1);
|
|
31
29
|
return usedBefore < this.limit
|
|
32
30
|
? { allowed: true, retryAfterSec: 0, remaining: this.limit - usedBefore - 1 }
|
|
33
31
|
: { allowed: false, retryAfterSec: Math.max(1, this.counter.retryAfterSec()), remaining: 0 };
|
|
34
32
|
}
|
|
35
|
-
/** The flush loop self-reaps old windows; the periodic sweeper has nothing to do for this backend. */
|
|
36
33
|
sweep() {
|
|
37
|
-
/* no-op */
|
|
38
34
|
}
|
|
39
|
-
// write-behind lifecycle (delegated; exposed for tests/parity)
|
|
40
35
|
flush() {
|
|
41
36
|
return this.counter.flush();
|
|
42
37
|
}
|
|
@@ -54,11 +49,6 @@ export class PgRateLimiter {
|
|
|
54
49
|
this.counter.stop();
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
|
-
/**
|
|
58
|
-
* PG translation of tidb-pool's `rate_limit` DDL (SCHEMA_STATEMENTS): INT→INTEGER, DATETIME(3)→TIMESTAMPTZ(3),
|
|
59
|
-
* inline `KEY idx_window`→separate `CREATE INDEX`. The composite PK (limit_key, window_bucket) backs the
|
|
60
|
-
* atomic ON CONFLICT increment.
|
|
61
|
-
*/
|
|
62
52
|
export const PG_RATE_LIMITER_SCHEMA = [
|
|
63
53
|
`CREATE TABLE IF NOT EXISTS rate_limit (
|
|
64
54
|
limit_key VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -69,7 +59,6 @@ export const PG_RATE_LIMITER_SCHEMA = [
|
|
|
69
59
|
)`,
|
|
70
60
|
`CREATE INDEX IF NOT EXISTS idx_rate_limit_window ON rate_limit (window_bucket)`,
|
|
71
61
|
];
|
|
72
|
-
/** Self-contained schema bootstrap for tests (the rate_limit table is disjoint from other stores). */
|
|
73
62
|
export async function ensureSchema(pool) {
|
|
74
63
|
for (const stmt of PG_RATE_LIMITER_SCHEMA)
|
|
75
64
|
await pool.query(stmt);
|
|
@@ -1,26 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PG 写入臂族的统一序列化([1439]/[1442]test CF-UNICODE + codex 四 high 复审)。
|
|
3
|
-
*
|
|
4
|
-
* 病:PG 的 text/jsonb 域**不可存 NUL**(ERRCODE 22P05/22021),unpaired surrogate 同族——tool_result
|
|
5
|
-
* 夹带真 0x00(agent raw `cat` 二进制/含 NUL 文件)→ 写入即炸 → session append 崩、run 中途死
|
|
6
|
-
* (云独有指纹:file store 无此约束,[1438]②/[1439] 定谳归 server)。
|
|
7
|
-
*
|
|
8
|
-
* 三层工具,按臂的保真需求选用:
|
|
9
|
-
* - {@link pgSanitizeText}:裸 text 列(memory body / tool_result content)。
|
|
10
|
-
* - {@link pgSafeJsonStringify}:**深度** sanitize(键+值都扫——codex H2:replacer 换不了键名,
|
|
11
|
-
* 含 NUL 的属性名照样炸;撞键以 U+FFFD 追加消歧,诚实不静默覆盖)后 stringify。有损(U+FFFD),
|
|
12
|
-
* 用于观测/记账类 blob(session event、run 行、outcome、journal——内容语义容忍替换标记)。
|
|
13
|
-
* - {@link pgLosslessJsonStringify}/{@link pgLosslessJsonParse}:**无损信封**(codex H1:checkpoint 的
|
|
14
|
-
* pendingAction args 过 approval 信任边界,hash 绑定原文,有损替换=执行内容偏离已批内容)。
|
|
15
|
-
* 干净值原样直存(既有行形不变);含不可存码点才折 `{__pgSafeB64}` 信封(base64 承载 stringify
|
|
16
|
-
* 原文——stringify 输出恒 well-formed 转义形,base64 逐位保真),读侧解封逐位还原。
|
|
17
|
-
*/
|
|
18
1
|
const NUL_OR_LONE_SURROGATE = /\u0000|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
19
2
|
export function pgSanitizeText(s) {
|
|
20
3
|
return s.replace(NUL_OR_LONE_SURROGATE, "�");
|
|
21
4
|
}
|
|
22
|
-
/** 深度 sanitize:字符串值+**属性名**都扫(数组递归;非 plain 值原样)。输入应为 JSON-plain 树
|
|
23
|
-
* (调用方先过 `JSON.parse(JSON.stringify(v))` 保 toJSON/undefined 语义——见 pgSafeJsonStringify)。 */
|
|
24
5
|
function sanitizeDeep(v, state) {
|
|
25
6
|
if (typeof v === "string") {
|
|
26
7
|
const s = pgSanitizeText(v);
|
|
@@ -31,13 +12,13 @@ function sanitizeDeep(v, state) {
|
|
|
31
12
|
if (Array.isArray(v))
|
|
32
13
|
return v.map((x) => sanitizeDeep(x, state));
|
|
33
14
|
if (v !== null && typeof v === "object") {
|
|
34
|
-
const out = Object.create(null);
|
|
15
|
+
const out = Object.create(null);
|
|
35
16
|
for (const [k, val] of Object.entries(v)) {
|
|
36
17
|
let key = pgSanitizeText(k);
|
|
37
18
|
if (key !== k)
|
|
38
19
|
state.changed = true;
|
|
39
20
|
while (Object.prototype.hasOwnProperty.call(out, key)) {
|
|
40
|
-
key += "�";
|
|
21
|
+
key += "�";
|
|
41
22
|
state.changed = true;
|
|
42
23
|
}
|
|
43
24
|
out[key] = sanitizeDeep(val, state);
|
|
@@ -46,27 +27,20 @@ function sanitizeDeep(v, state) {
|
|
|
46
27
|
}
|
|
47
28
|
return v;
|
|
48
29
|
}
|
|
49
|
-
/** 有损深度安全 stringify(键+值)。 */
|
|
50
30
|
export function pgSafeJsonStringify(value) {
|
|
51
31
|
const raw = JSON.stringify(value);
|
|
52
32
|
if (raw === undefined)
|
|
53
|
-
return raw;
|
|
54
|
-
const plain = JSON.parse(raw);
|
|
33
|
+
return raw;
|
|
34
|
+
const plain = JSON.parse(raw);
|
|
55
35
|
const state = { changed: false };
|
|
56
36
|
const clean = sanitizeDeep(plain, state);
|
|
57
37
|
return state.changed ? JSON.stringify(clean) : raw;
|
|
58
38
|
}
|
|
59
39
|
const ENVELOPE_KEY = "__pgSafe";
|
|
60
40
|
const ENVELOPE_VERSION = "b64.v1";
|
|
61
|
-
/** 信封判别:**精确形**(恰两键 {__pgSafe:"b64.v1", d:string})——codex R2-H2:单键存在性判别会把
|
|
62
|
-
* 「恰好带同名键的普通用户 JSON/老行」误当信封(合法 base64 静默解出别的对象、非 base64 读侧炸)。
|
|
63
|
-
* 精确形+版本号把碰撞面收到「用户恰好存逐位同形信封」,由 stringify 侧转义规避(见下)。 */
|
|
64
41
|
function isEnvelope(o) {
|
|
65
42
|
return Object.keys(o).length === 2 && o[ENVELOPE_KEY] === ENVELOPE_VERSION && typeof o.d === "string";
|
|
66
43
|
}
|
|
67
|
-
/** 无损:干净值原样;脏值折版本化信封(读侧 {@link pgLosslessJsonParse} 逐位还原)。干净值若**恰为
|
|
68
|
-
* 保留形**(用户数据撞信封/转义形)→ 套 {__pgSafe:"esc.v1", d:<原文>} 转义一层,读侧解一层——
|
|
69
|
-
* 保留形永不与用户数据歧义。 */
|
|
70
44
|
export function pgLosslessJsonStringify(value) {
|
|
71
45
|
const raw = JSON.stringify(value);
|
|
72
46
|
if (raw === undefined)
|
|
@@ -83,12 +57,8 @@ export function pgLosslessJsonStringify(value) {
|
|
|
83
57
|
}
|
|
84
58
|
return raw;
|
|
85
59
|
}
|
|
86
|
-
// stringify 输出恒 well-formed(NUL/lone surrogate 均已是六字符转义),utf8→base64 逐位保真。
|
|
87
60
|
return JSON.stringify({ [ENVELOPE_KEY]: ENVELOPE_VERSION, d: Buffer.from(raw, "utf8").toString("base64") });
|
|
88
61
|
}
|
|
89
|
-
/** detect-only:值树里是否含不可存码点(字符串值+属性名都查,零形变零拷贝)。干净输入(绝大多数)
|
|
90
|
-
* 让调用方走**引用原样**快路——canonical 化的 JSON round-trip 对干净输入也可能形变(undefined 值键
|
|
91
|
-
* 剥离等),CAS/rev 语义的臂必须先 detect 再变换。 */
|
|
92
62
|
export function pgHasUnstorable(v) {
|
|
93
63
|
if (typeof v === "string")
|
|
94
64
|
return NUL_OR_LONE_SURROGATE.test(v) ? (NUL_OR_LONE_SURROGATE.lastIndex = 0, true) : false;
|
|
@@ -102,11 +72,6 @@ export function pgHasUnstorable(v) {
|
|
|
102
72
|
}
|
|
103
73
|
return false;
|
|
104
74
|
}
|
|
105
|
-
/** codex R4→R7 终形:协议数据(approval args/checkpoint/ctx/outcome/rules/memory)一律**拒绝式**。
|
|
106
|
-
* 信封方案历经 R4-R7 四轮对抗全灭:行内判别子恒可被 ≤1.240 老行/用户数据撞形(静默解错=approval
|
|
107
|
-
* 信任边界破),进程旗恒有混旗副本窗(写读不同解)。唯一无歧义解=**脏值不进库**:PG 存不了
|
|
108
|
-
* NUL 是后端能力边界,fail-loud 暴露(清晰文案)严格优于修前的 22P05 神秘崩——两者都存不进,
|
|
109
|
-
* 但拒绝式下 review==execute 恒成立(库里只有干净值,展示面=执行面永逐位一致)。 */
|
|
110
75
|
export class PgUnstorableError extends Error {
|
|
111
76
|
constructor(what) {
|
|
112
77
|
super(`${what} contains bytes PostgreSQL cannot store (NUL / lone surrogate). ` +
|
|
@@ -114,7 +79,6 @@ export class PgUnstorableError extends Error {
|
|
|
114
79
|
this.name = "PgUnstorableError";
|
|
115
80
|
}
|
|
116
81
|
}
|
|
117
|
-
/** 协议数据写面:干净=原样 stringify;脏={@link PgUnstorableError} fail-loud。 */
|
|
118
82
|
export function pgProtocolJsonStringify(value, what) {
|
|
119
83
|
const raw = JSON.stringify(value);
|
|
120
84
|
if (raw === undefined)
|