@sema-agent/server 7.146.0 → 7.148.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 +1423 -24
- package/README.md +21 -8
- package/README.zh-CN.md +15 -9
- package/USAGE.md +537 -216
- package/deploy/facts/lanes.json +7 -0
- package/deploy/sema-up/README.md +18 -7
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +42 -4
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
- package/deploy/sema-up/chart/templates/server.yaml +5 -4
- package/deploy/sema-up/chart/values.yaml +4 -3
- package/deploy/sema-up/cluster-up.sh +75 -176
- package/deploy/sema-up/kube-up.sh +29 -49
- package/deploy/sema-up/lib/chart-run.sh +23 -0
- package/deploy/sema-up/lib/dataroot.sh +3 -3
- package/deploy/sema-up/lib/flagshape.sh +4 -0
- package/deploy/sema-up/lib/health.sh +62 -13
- package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
- package/deploy/sema-up/lib/helm-values-kube.py +35 -0
- package/deploy/sema-up/lib/lanes.json +2 -5
- package/deploy/sema-up/lib/regcred.py +8 -0
- package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
- package/deploy/sema-up/lib/remote/image-import.sh +6 -0
- package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
- package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
- package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
- package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
- package/deploy/sema-up/lib/render-stack.py +17 -0
- package/deploy/sema-up/lib/shell-text.sh +87 -0
- package/deploy/sema-up/lib/usage-flags.txt +10 -0
- package/deploy/sema-up/lib/usage-head.txt +1 -0
- package/deploy/sema-up/lib/usage-tail.txt +13 -0
- package/deploy/sema-up/preflight.sh +10 -8
- package/deploy/sema-up/sema-up.sh +26 -48
- package/deploy/sema-up/smoke.sh +7 -6
- package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
- package/deploy/sema-up/stack/compose.yaml +18 -5
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +25 -3
- package/dist/adoption/plan.d.ts +24 -0
- package/dist/adoption/plan.js +53 -1
- package/dist/adoption/runner.d.ts +10 -1
- package/dist/adoption/runner.js +36 -16
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +32 -34
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +16 -14
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +17 -9
- package/dist/auth-bridge.d.ts +0 -14
- package/dist/auth-bridge.js +0 -7
- package/dist/auto-mode-face.d.ts +10 -7
- package/dist/auto-mode-face.js +7 -4
- package/dist/background-agent-name.d.ts +19 -1
- package/dist/background-agent-name.js +12 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.js +9 -6
- package/dist/bench/s1/arms.js +6 -5
- package/dist/bench/s1/live-deps.js +8 -3
- package/dist/bench/s1/run-firm.js +6 -5
- package/dist/bind-host.d.ts +25 -0
- package/dist/bind-host.js +25 -0
- package/dist/boot/adoption.d.ts +3 -0
- package/dist/boot/adoption.js +1 -0
- package/dist/boot/crash-last.js +2 -1
- package/dist/boot/deployment-mods.d.ts +1 -1
- package/dist/boot/device-lane.js +5 -5
- package/dist/boot/engine-lease.d.ts +12 -11
- package/dist/boot/execution-env.d.ts +19 -8
- package/dist/boot/execution-env.js +80 -62
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +3 -3
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/exit-last.js +2 -1
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +18 -16
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +50 -53
- package/dist/boot/memory-consolidation.js +11 -18
- package/dist/boot/org-memory.js +4 -3
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +3 -3
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +20 -17
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +133 -165
- package/dist/boot/retention-lane.d.ts +7 -45
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +11 -4
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +17 -7
- package/dist/boot/session-faces.js +122 -96
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +14 -2
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -1
- package/dist/boot/stage-02-web-admin-pull.js +15 -8
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -1
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +9 -5
- package/dist/boot/stage-05-execution-env.js +5 -5
- package/dist/boot/stage-06-runners.d.ts +13 -15
- package/dist/boot/stage-06-runners.js +24 -18
- package/dist/boot/stage-07-capability-layer.d.ts +14 -11
- package/dist/boot/stage-07-capability-layer.js +9 -12
- package/dist/boot/stage-08-reapers.d.ts +14 -11
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +16 -18
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +16 -18
- package/dist/boot/stage-10-http-server.js +9 -5
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +12 -0
- package/dist/boot/stores.js +39 -17
- package/dist/boot/task-list-lane.d.ts +4 -4
- package/dist/boot/web-admin.d.ts +4 -2
- package/dist/boot/web-admin.js +58 -38
- package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
- package/dist/boot-reclaim.d.ts +3 -1
- package/dist/boot-reclaim.js +1 -1
- package/dist/brain.d.ts +7 -18
- package/dist/brain.js +5 -17
- package/dist/budget.js +6 -6
- package/dist/capabilities/center-plugins.d.ts +9 -1
- package/dist/capabilities/center-plugins.js +37 -11
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +3 -2
- package/dist/capabilities/composite-members.js +3 -2
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +38 -33
- package/dist/capabilities/scenarios.js +24 -25
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +6 -6
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +69 -4
- package/dist/capability-facts.js +77 -5
- package/dist/card-void.d.ts +4 -4
- package/dist/card-void.js +1 -1
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +10 -5
- package/dist/config-catalog.d.ts +16 -1
- package/dist/config-catalog.js +68 -61
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +58 -4
- package/dist/config-invariants.js +104 -23
- package/dist/config-lkg.d.ts +24 -2
- package/dist/config-lkg.js +22 -9
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -108
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +215 -202
- package/dist/config.d.ts +69 -14
- package/dist/config.js +188 -96
- package/dist/degenerate-instrument.js +1 -1
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deploy-facts.js +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +51 -16
- package/dist/deployment-shape.js +31 -6
- package/dist/egress-redirect.d.ts +25 -7
- package/dist/egress-redirect.js +20 -2
- package/dist/elicitation.d.ts +6 -5
- package/dist/elicitation.js +23 -22
- package/dist/engine-identity.d.ts +28 -0
- package/dist/engine-identity.js +10 -0
- package/dist/entry-problems.d.ts +5 -7
- package/dist/entry-problems.js +1 -1
- package/dist/env-facts.d.ts +7 -5
- package/dist/env-facts.js +12 -7
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +53 -103
- package/dist/execution-lane-caps.js +51 -83
- package/dist/execution-placement.d.ts +65 -9
- package/dist/execution-placement.js +58 -0
- package/dist/field-conflict.d.ts +7 -11
- package/dist/field-conflict.js +3 -3
- package/dist/file-history-capture.d.ts +3 -3
- package/dist/file-history-disclosure.d.ts +2 -2
- package/dist/file-history-disclosure.js +1 -0
- package/dist/fleet/drain-entry.d.ts +17 -10
- package/dist/fleet/drain-entry.js +1 -1
- package/dist/fleet/fleet-bus.d.ts +21 -3
- package/dist/fleet/fleet-bus.js +35 -25
- package/dist/fleet/fleet-reconciler.js +2 -2
- package/dist/fleet/serving-lease.js +6 -7
- package/dist/fleet-client.js +3 -3
- package/dist/fleet-lease.d.ts +0 -1
- package/dist/fleet-lease.js +4 -5
- package/dist/history-anchor.d.ts +42 -0
- package/dist/history-anchor.js +34 -0
- package/dist/hitl-delivery.d.ts +90 -0
- package/dist/hitl-delivery.js +98 -0
- package/dist/hooks/classic-stations.d.ts +8 -11
- package/dist/hooks/classic-stations.js +0 -7
- package/dist/hooks/command-spawn.d.ts +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +119 -65
- package/dist/hooks/hook-runner.js +415 -217
- package/dist/host-lsp-manager.d.ts +22 -8
- package/dist/host-lsp-manager.js +4 -1
- package/dist/http/active-run-conflict.d.ts +2 -43
- package/dist/http/active-run-conflict.js +3 -7
- package/dist/http/admission.d.ts +4 -18
- package/dist/http/admission.js +75 -78
- package/dist/http/approval-sweeps.d.ts +5 -8
- package/dist/http/approval-sweeps.js +55 -30
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/checkpoint-ctx.d.ts +17 -0
- package/dist/http/checkpoint-ctx.js +6 -0
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +77 -31
- package/dist/http/durable-run-leg.d.ts +3 -3
- package/dist/http/durable-run-leg.js +18 -12
- package/dist/http/execution-context.d.ts +18 -42
- package/dist/http/execution-context.js +11 -5
- package/dist/http/health-reader.d.ts +36 -0
- package/dist/http/health-reader.js +21 -0
- package/dist/http/health-self-report.d.ts +9 -9
- package/dist/http/health-self-report.js +4 -4
- package/dist/http/idempotency.d.ts +9 -5
- package/dist/http/idempotency.js +4 -4
- package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
- package/dist/http/memory-compliance-failure-reply.js +7 -2
- package/dist/http/memory-face-fault-reply.d.ts +67 -0
- package/dist/http/memory-face-fault-reply.js +71 -0
- package/dist/http/memory-store-refusal-reply.d.ts +3 -3
- package/dist/http/memory-store-refusal-reply.js +6 -0
- package/dist/http/owner-access.d.ts +391 -56
- package/dist/http/owner-access.js +372 -33
- package/dist/http/principal-gate.d.ts +26 -94
- package/dist/http/principal-gate.js +24 -81
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +10 -14
- package/dist/http/request-guards.js +34 -68
- package/dist/http/resume-composition.d.ts +37 -0
- package/dist/http/resume-composition.js +18 -0
- package/dist/http/resume-ctx-read.d.ts +35 -12
- package/dist/http/resume-ctx-read.js +25 -6
- package/dist/http/resume-legs.d.ts +24 -24
- package/dist/http/resume-legs.js +260 -171
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +56 -47
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +58 -37
- package/dist/http/routes/admin-config-refresh.js +2 -2
- package/dist/http/routes/admin-drain.js +2 -2
- package/dist/http/routes/admin-memory-optout.js +4 -3
- package/dist/http/routes/adoption.d.ts +3 -0
- package/dist/http/routes/adoption.js +17 -10
- package/dist/http/routes/agents-roster.js +13 -7
- package/dist/http/routes/approvals-assistant.js +73 -88
- package/dist/http/routes/attachments.js +2 -2
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/background.js +9 -17
- package/dist/http/routes/capabilities.js +23 -20
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +5 -5
- package/dist/http/routes/diagnostics.d.ts +27 -3
- package/dist/http/routes/diagnostics.js +27 -21
- package/dist/http/routes/engine.js +2 -2
- package/dist/http/routes/fleet.js +5 -3
- package/dist/http/routes/images.js +10 -6
- package/dist/http/routes/leader.d.ts +7 -2
- package/dist/http/routes/leader.js +12 -3
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +7 -15
- package/dist/http/routes/memory-bundle.js +4 -7
- package/dist/http/routes/memory-compliance.js +4 -4
- package/dist/http/routes/memory-consolidation.js +6 -9
- package/dist/http/routes/memory-origin.d.ts +3 -1
- package/dist/http/routes/memory-origin.js +7 -8
- package/dist/http/routes/memory-policy.js +17 -12
- package/dist/http/routes/notify-wake.js +12 -20
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +1 -1
- package/dist/http/routes/principal-inbox.js +2 -2
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +87 -0
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +50 -7
- package/dist/http/routes/run-memory-capture.d.ts +2 -2
- package/dist/http/routes/run-memory-capture.js +6 -12
- package/dist/http/routes/run-permission-mode.d.ts +2 -2
- package/dist/http/routes/run-permission-mode.js +10 -17
- package/dist/http/routes/runs.js +148 -233
- package/dist/http/routes/session-memory-sync.d.ts +2 -2
- package/dist/http/routes/session-memory-sync.js +7 -13
- package/dist/http/routes/session-sync.d.ts +4 -2
- package/dist/http/routes/session-sync.js +48 -30
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +177 -112
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +144 -122
- package/dist/http/routes/trace-usage.d.ts +0 -12
- package/dist/http/routes/trace-usage.js +40 -46
- package/dist/http/routes/workflows.d.ts +39 -4
- package/dist/http/routes/workflows.js +42 -14
- package/dist/http/run-concurrency-cap.d.ts +20 -12
- package/dist/http/run-concurrency-cap.js +39 -26
- package/dist/http/run-read-face.d.ts +3 -5
- package/dist/http/run-read-face.js +8 -13
- package/dist/http/send.d.ts +12 -3
- package/dist/http/send.js +42 -6
- package/dist/http/server.d.ts +63 -50
- package/dist/http/server.js +52 -16
- package/dist/http/sse-log.d.ts +17 -10
- package/dist/http/sse-log.js +7 -7
- package/dist/http/stored-body-replay.d.ts +17 -3
- package/dist/http/stored-body-replay.js +11 -2
- package/dist/http/submit-ctx.d.ts +16 -8
- package/dist/http/submit-ctx.js +6 -2
- package/dist/http/submit-replay.d.ts +19 -6
- package/dist/http/submit-replay.js +18 -6
- package/dist/http/sync-submit-body.d.ts +3 -4
- package/dist/http/sync-submit-body.js +4 -5
- package/dist/http/wire-types.d.ts +23 -13
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- package/dist/key-resolver.d.ts +32 -0
- package/dist/key-resolver.js +23 -9
- package/dist/leader/diffup.js +2 -1
- package/dist/leader/endpoint.d.ts +26 -5
- package/dist/leader/endpoint.js +154 -14
- package/dist/leader/fanout.d.ts +3 -0
- package/dist/leader/fanout.js +78 -63
- package/dist/leader/leader.d.ts +16 -0
- package/dist/leader/leader.js +43 -3
- package/dist/leader/merge.d.ts +9 -1
- package/dist/leader/merge.js +16 -1
- package/dist/leader/repair-wire.js +1 -1
- package/dist/leader/wire.d.ts +36 -3
- package/dist/leader/wire.js +59 -18
- package/dist/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-scope.d.ts +31 -4
- package/dist/memory-scope.js +65 -16
- package/dist/memory-store-refusal.d.ts +20 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +5 -2
- package/dist/memory-sync-client.js +19 -14
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +51 -28
- package/dist/model-compat.js +55 -23
- package/dist/model-context-window.d.ts +18 -0
- package/dist/model-context-window.js +2 -0
- package/dist/model-entry-headers.d.ts +46 -4
- package/dist/model-entry-headers.js +2 -2
- package/dist/model-entry-refusal.d.ts +46 -17
- package/dist/model-entry-refusal.js +47 -27
- package/dist/model-plane-face.d.ts +19 -11
- package/dist/model-plane-face.js +9 -1
- package/dist/model-plane-probe.d.ts +2 -0
- package/dist/model-plane-probe.js +17 -0
- package/dist/model-provider.d.ts +3 -3
- package/dist/model-route-endpoint.d.ts +9 -5
- package/dist/model-route-endpoint.js +29 -7
- package/dist/model-select.d.ts +16 -0
- package/dist/model-select.js +4 -0
- package/dist/mountinfo.d.ts +37 -0
- package/dist/mountinfo.js +47 -0
- package/dist/namespaced-rule-name.d.ts +28 -2
- package/dist/namespaced-rule-name.js +10 -1
- package/dist/net-address.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +4 -4
- package/dist/observability/corrupt-read-seat.js +5 -3
- package/dist/observability/fail-open.d.ts +75 -47
- package/dist/observability/fail-open.js +77 -47
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +5 -4
- package/dist/observability/otel-exporter.js +2 -1
- package/dist/observability/principal-context.d.ts +14 -7
- package/dist/observability/principal-context.js +8 -3
- package/dist/observability/run-terminal.d.ts +7 -1
- package/dist/observability/run-terminal.js +5 -2
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
- package/dist/orchestration/hardened-vm-runner.js +11 -5
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
- package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
- package/dist/orchestration/hardened-vm-worker.js +2 -1
- package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +29 -9
- package/dist/orchestration/workflow-completion-inbox.js +65 -46
- package/dist/org-delivery-gate.d.ts +5 -4
- package/dist/org-delivery-gate.js +7 -6
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- package/dist/outbound-dispatcher.d.ts +1 -1
- package/dist/outbound-dispatcher.js +6 -12
- package/dist/owner-brands.d.ts +81 -0
- package/dist/owner-brands.js +42 -0
- package/dist/owner-faces.d.ts +531 -0
- package/dist/owner-faces.js +126 -0
- package/dist/parked-decide.d.ts +100 -31
- package/dist/parked-decide.js +162 -48
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +6 -8
- package/dist/peer-directory.js +3 -2
- package/dist/permission-rule-vocab.d.ts +53 -8
- package/dist/permission-rule-vocab.js +30 -2
- package/dist/plugins/adoption-log-sql.d.ts +0 -22
- package/dist/plugins/adoption-log-sql.js +5 -3
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
- package/dist/plugins/approval-ask-store-file.d.ts +28 -9
- package/dist/plugins/approval-ask-store-file.js +74 -18
- package/dist/plugins/approval-ask-store-memory.d.ts +17 -7
- package/dist/plugins/approval-ask-store-memory.js +35 -12
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -20
- package/dist/plugins/approval-ask-store-sql.js +44 -11
- package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
- package/dist/plugins/approval-exemption-skill-m46.js +25 -0
- package/dist/plugins/approval-exemption-store.d.ts +6 -1
- package/dist/plugins/approval-exemption-store.js +14 -0
- package/dist/plugins/approval-nonce-store.d.ts +39 -12
- package/dist/plugins/approval-nonce-store.js +72 -23
- package/dist/plugins/blob-backend.d.ts +40 -195
- package/dist/plugins/blob-backend.js +41 -234
- package/dist/plugins/caching-session-store.d.ts +22 -5
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +33 -6
- package/dist/plugins/checkpoint-index-columns.js +39 -3
- package/dist/plugins/checkpoint-store-face.d.ts +84 -11
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +6 -10
- package/dist/plugins/ensure-index.d.ts +13 -1
- package/dist/plugins/ensure-index.js +154 -21
- package/dist/plugins/ensure-schema-lock-policy.d.ts +0 -15
- package/dist/plugins/ensure-schema-lock-policy.js +3 -2
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +89 -35
- package/dist/plugins/file-run-store.js +197 -142
- package/dist/plugins/host-platform.d.ts +24 -3
- package/dist/plugins/host-platform.js +15 -1
- package/dist/plugins/image-bake-store-sql.js +2 -0
- package/dist/plugins/imported-layer-root-retirement.d.ts +19 -10
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
- package/dist/plugins/k8s-pod-reaper.js +0 -1
- package/dist/plugins/leader-run-store-sql.d.ts +22 -0
- package/dist/plugins/leader-run-store-sql.js +34 -4
- package/dist/plugins/local-checkpoint-store.d.ts +63 -23
- package/dist/plugins/local-checkpoint-store.js +204 -81
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +183 -0
- package/dist/plugins/local-docker-capacity.d.ts +93 -0
- package/dist/plugins/local-docker-capacity.js +194 -0
- package/dist/plugins/local-docker-reaper.d.ts +92 -0
- package/dist/plugins/local-docker-reaper.js +102 -0
- package/dist/plugins/local-engine-high-water.d.ts +13 -0
- package/dist/plugins/local-engine-high-water.js +62 -0
- package/dist/plugins/local-session-store.d.ts +442 -143
- package/dist/plugins/local-session-store.js +941 -289
- package/dist/plugins/local-session-window.d.ts +3 -2
- package/dist/plugins/local-session-window.js +3 -2
- package/dist/plugins/local-sidecar-quarantine.js +3 -2
- package/dist/plugins/local-task-attachment-store.d.ts +20 -1
- package/dist/plugins/local-task-attachment-store.js +32 -12
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +11 -9
- package/dist/plugins/memory-engine-pg.d.ts +7 -5
- package/dist/plugins/memory-engine-pg.js +18 -9
- package/dist/plugins/memory-engine-sql-apply.d.ts +21 -8
- package/dist/plugins/memory-engine-sql-apply.js +7 -9
- package/dist/plugins/memory-engine-tidb.d.ts +12 -7
- package/dist/plugins/memory-engine-tidb.js +18 -10
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
- package/dist/plugins/memory-run-store.d.ts +39 -27
- package/dist/plugins/memory-run-store.js +72 -70
- package/dist/plugins/one-time-migration-marker.d.ts +10 -0
- package/dist/plugins/one-time-migration-marker.js +7 -0
- package/dist/plugins/one-time-migrations.d.ts +325 -74
- package/dist/plugins/one-time-migrations.js +705 -230
- package/dist/plugins/org-delivery-quota-store.js +2 -1
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +11 -11
- package/dist/plugins/permission-rule-store-file.js +14 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
- package/dist/plugins/permission-rule-store-sql.js +6 -86
- package/dist/plugins/pg-pool.d.ts +3 -32
- package/dist/plugins/pg-pool.js +27 -11
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +19 -28
- package/dist/plugins/remote-env-e2b.js +40 -29
- package/dist/plugins/remote-env-host.d.ts +11 -10
- package/dist/plugins/remote-env-host.js +40 -27
- package/dist/plugins/remote-env-k8s.d.ts +45 -47
- package/dist/plugins/remote-env-k8s.js +122 -62
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +370 -75
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +158 -0
- package/dist/plugins/retention-deployment.js +119 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- package/dist/plugins/run-preview-m45.d.ts +11 -0
- package/dist/plugins/run-preview-m45.js +19 -0
- package/dist/plugins/run-store-sql.d.ts +56 -68
- package/dist/plugins/run-store-sql.js +127 -116
- package/dist/plugins/s3-answer.d.ts +2 -1
- package/dist/plugins/sandbox-reaper.d.ts +26 -0
- package/dist/plugins/sandbox-reaper.js +2 -0
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +54 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +55 -0
- package/dist/plugins/scheduler-support.d.ts +16 -1
- package/dist/plugins/scheduler-support.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +42 -15
- package/dist/plugins/schema-consistency.js +213 -13
- package/dist/plugins/schema-drift-sentence.d.ts +4 -1
- package/dist/plugins/schema-drift-sentence.js +4 -4
- package/dist/plugins/schema-ensure-legs.d.ts +10 -1
- package/dist/plugins/schema-ensure-legs.js +12 -2
- package/dist/plugins/schema-indexes.js +3 -0
- package/dist/plugins/schema-live-columns.d.ts +14 -5
- package/dist/plugins/schema-live-columns.js +10 -10
- package/dist/plugins/send-user-file.js +2 -1
- package/dist/plugins/session-birth.d.ts +37 -0
- package/dist/plugins/session-birth.js +38 -0
- package/dist/plugins/session-epoch-anchor.d.ts +40 -12
- package/dist/plugins/session-epoch-anchor.js +33 -11
- package/dist/plugins/session-ext-table.d.ts +98 -0
- package/dist/plugins/session-ext-table.js +134 -0
- package/dist/plugins/session-fork.d.ts +16 -2
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +22 -16
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +20 -7
- package/dist/plugins/session-row-sql.js +16 -8
- package/dist/plugins/session-run-rollup.d.ts +29 -0
- package/dist/plugins/session-run-rollup.js +40 -0
- package/dist/plugins/session-store-sql.d.ts +157 -0
- package/dist/plugins/session-store-sql.js +398 -0
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -69
- package/dist/plugins/shared-memory-store-sql.js +15 -14
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +20 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +24 -8
- package/dist/plugins/sql-driver.js +43 -9
- package/dist/plugins/sql-errors.d.ts +35 -5
- package/dist/plugins/sql-errors.js +55 -3
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/store-backend.d.ts +114 -18
- package/dist/plugins/store-backend.js +340 -87
- package/dist/plugins/store-contracts.d.ts +97 -30
- package/dist/plugins/store-contracts.js +23 -1
- package/dist/plugins/store-fault.d.ts +28 -2
- package/dist/plugins/store-fault.js +20 -2
- package/dist/plugins/task-attachment-store.d.ts +21 -11
- package/dist/plugins/task-attachment-store.js +37 -19
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +42 -39
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- package/dist/plugins/web-search.js +5 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
- package/dist/plugins/workflow-run-store-sql.js +11 -5
- package/dist/principal-jwt.d.ts +4 -4
- package/dist/principal-jwt.js +20 -5
- package/dist/principal-shape.d.ts +41 -0
- package/dist/principal-shape.js +19 -0
- package/dist/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- package/dist/request-declaration-refusal.d.ts +35 -12
- package/dist/request-declaration-refusal.js +21 -9
- package/dist/request-form.d.ts +58 -0
- package/dist/request-form.js +72 -0
- package/dist/request-image-urls.d.ts +8 -2
- package/dist/request-image-urls.js +2 -1
- package/dist/request-images.d.ts +20 -0
- package/dist/request-images.js +59 -0
- package/dist/request-key-closure.d.ts +6 -7
- package/dist/request-key-closure.js +15 -2
- package/dist/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- package/dist/resource-suspend.d.ts +7 -16
- package/dist/resource-suspend.js +1 -1
- package/dist/retired-name-host-notice.d.ts +21 -0
- package/dist/retired-name-host-notice.js +12 -0
- package/dist/rule-entry-list.d.ts +2 -2
- package/dist/rule-entry-list.js +3 -4
- package/dist/rule-issue-reading.d.ts +58 -0
- package/dist/rule-issue-reading.js +14 -0
- package/dist/rules-consent.d.ts +46 -16
- package/dist/rules-consent.js +102 -53
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +109 -93
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +73 -44
- package/dist/runs.js +65 -43
- package/dist/runtime-caps-resolver.d.ts +36 -14
- package/dist/runtime-caps-resolver.js +31 -14
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -6
- package/dist/sealed-key-layout.js +5 -1
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +116 -26
- package/dist/security.d.ts +133 -161
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +27 -2
- package/dist/server-secret-env.d.ts +23 -5
- package/dist/server-secret-env.js +14 -4
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-children-retire.d.ts +7 -5
- package/dist/session-children-retire.js +7 -2
- package/dist/session-deletion.d.ts +88 -0
- package/dist/session-deletion.js +8 -0
- package/dist/session-erase.d.ts +145 -0
- package/dist/session-erase.js +115 -0
- package/dist/session-error-wire.d.ts +6 -6
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +60 -10
- package/dist/session-incarnation.js +19 -2
- package/dist/session-policy-wire.d.ts +6 -3
- package/dist/session-policy-wire.js +11 -1
- package/dist/session-resident-background.d.ts +29 -47
- package/dist/session-resident-background.js +77 -8
- package/dist/session-row.d.ts +3 -2
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-sync-kernel.d.ts +1 -1
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +11 -2
- package/dist/session-workspace.js +5 -0
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-posture.d.ts +138 -21
- package/dist/store-posture.js +188 -3
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +21 -16
- package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
- package/dist/stores-sql/background-agent-store-sql.js +73 -20
- package/dist/stores-sql/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +86 -71
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +30 -81
- package/dist/{plugins → stores-sql}/pg-session-storage.js +123 -244
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +197 -223
- package/dist/{plugins → stores-sql}/retention-store-sql.js +148 -207
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +33 -11
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +65 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +14 -15
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +22 -28
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +67 -138
- package/dist/{plugins → stores-sql}/tidb-session-store.js +130 -200
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +1 -1
- package/dist/stores-sql/windowed-session-storage.d.ts +61 -0
- package/dist/stores-sql/windowed-session-storage.js +70 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +18 -17
- package/dist/task-cwd.d.ts +31 -3
- package/dist/task-cwd.js +25 -1
- package/dist/task-mcp.d.ts +11 -3
- package/dist/task-mcp.js +16 -19
- package/dist/task-settings.d.ts +23 -14
- package/dist/task-settings.js +35 -13
- package/dist/terminal.d.ts +25 -43
- package/dist/terminal.js +31 -11
- package/dist/tool-approval.d.ts +152 -137
- package/dist/tool-approval.js +199 -199
- package/dist/trace/core-keyset-guard.d.ts +22 -9
- package/dist/trace/core-vocab-wire.d.ts +95 -0
- package/dist/trace/core-vocab-wire.js +15 -0
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +52 -4
- package/dist/trace/exit-seat.js +43 -36
- package/dist/trace/extension-call-face.d.ts +3 -2
- package/dist/trace/extension-call-face.js +3 -1
- package/dist/trace/ledger-events.d.ts +4 -7
- package/dist/trace/ledger-sink.d.ts +1 -30
- package/dist/trace/ledger-sink.js +0 -11
- package/dist/trace/model-segment.d.ts +5 -5
- package/dist/trace/model-segment.js +5 -5
- package/dist/trace/project.d.ts +88 -58
- package/dist/trace/project.js +64 -28
- package/dist/trace/redact.d.ts +124 -28
- package/dist/trace/redact.js +936 -328
- package/dist/trace/self-minted-wire.d.ts +750 -29
- package/dist/trace/self-minted-wire.js +262 -25
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +43 -8
- package/dist/trace/wire-projection-faces.js +28 -3
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- package/dist/upstream-body.d.ts +23 -0
- package/dist/upstream-body.js +16 -0
- package/dist/url-refusal.d.ts +3 -3
- package/dist/url-refusal.js +11 -4
- package/dist/user-authored-text.d.ts +1 -1
- package/dist/user-input-ledger.d.ts +7 -8
- package/dist/user-input-ledger.js +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +6 -3
- package/dist/web-admin-client/apply-effective.js +33 -40
- package/dist/web-admin-client/apply-ledger.d.ts +16 -7
- package/dist/web-admin-client/apply-ledger.js +5 -2
- package/dist/web-admin-client/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +6 -3
- package/dist/web-admin-client/center-request.js +17 -16
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -2
- package/dist/web-admin-client/entry-metadata.d.ts +8 -0
- package/dist/web-admin-client/entry-metadata.js +13 -0
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +2 -1
- package/dist/web-admin-client/http-client.js +40 -13
- package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
- package/dist/web-admin-client/mcp-revocation.js +2 -1
- package/dist/web-admin-client/read-warnings.d.ts +1 -0
- package/dist/web-admin-client/read-warnings.js +1 -0
- package/dist/web-admin-client/restart-signal.js +13 -6
- package/dist/web-admin-client/skills-mcp.d.ts +22 -8
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +35 -51
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/package.json +16 -12
- package/scripts/drain-check-local.mjs +118 -173
- package/scripts/drain-check.mysql.sql +20 -16
- package/scripts/drain-check.pg.sql +20 -16
- package/wire-changes/server@7.147.0.json +813 -0
- package/wire-changes/server@7.148.0.json +1517 -0
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
- package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
- package/dist/http/memory-layer-reply.d.ts +0 -30
- package/dist/http/memory-layer-reply.js +0 -24
- package/dist/lsp/e2b-bridge.d.ts +0 -57
- package/dist/lsp/e2b-bridge.js +0 -139
- package/dist/lsp/e2b-manager.d.ts +0 -93
- package/dist/lsp/e2b-manager.js +0 -178
- package/dist/lsp/lsp-frames.d.ts +0 -14
- package/dist/lsp/lsp-frames.js +0 -25
- package/dist/lsp/manager.d.ts +0 -129
- package/dist/lsp/manager.js +0 -127
- package/dist/lsp/types.d.ts +0 -12
- package/dist/lsp/types.js +0 -2
- package/dist/lsp/ws-transport.d.ts +0 -40
- package/dist/lsp/ws-transport.js +0 -210
package/dist/trace/redact.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { REDACTION_MARK, displayUrlOf, stripFormatCharacters } from "@sema-agent/core";
|
|
2
|
-
import { CONTROL_AND_BIDI_CHARS, CREDENTIAL_PARAM_NAMES, isHierarchicalUrl } from "@sema-agent/settings-schema";
|
|
2
|
+
import { CONTROL_AND_BIDI_CHARS, CREDENTIAL_PARAM_NAMES, credentialParamWordOf, isHierarchicalUrl } from "@sema-agent/settings-schema";
|
|
3
3
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
4
4
|
const normalizeForRedaction = stripFormatCharacters;
|
|
5
5
|
export function mapNormalizedToOriginal(text, normalized) {
|
|
@@ -29,6 +29,7 @@ export function mapNormalizedToOriginal(text, normalized) {
|
|
|
29
29
|
return map;
|
|
30
30
|
}
|
|
31
31
|
const SPELLED_FORMAT = 1, SPELLED_CONTROL = 2, RAW_CONTROL = 4, RAW_WHITESPACE = 8;
|
|
32
|
+
const RAW_IGNORABLE = 16, SPELLED_IGNORABLE = 32;
|
|
32
33
|
const INVISIBLE_UNIT_CLASS = (() => {
|
|
33
34
|
const inSet = new RegExp(`[${CONTROL_AND_BIDI_CHARS}]`);
|
|
34
35
|
const table = new Uint8Array(0x10000);
|
|
@@ -39,32 +40,72 @@ const INVISIBLE_UNIT_CLASS = (() => {
|
|
|
39
40
|
}
|
|
40
41
|
return table;
|
|
41
42
|
})();
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
const READING_IGNORABLE_CLASS = String.raw `\p{Default_Ignorable_Code_Point}\p{Mn}\p{Cc}`;
|
|
44
|
+
const READING_IGNORABLE_RE = new RegExp(`^[${READING_IGNORABLE_CLASS}]$`, "u");
|
|
45
|
+
function isReadingIgnorable(cp) {
|
|
46
|
+
if (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
|
|
47
|
+
return false;
|
|
48
|
+
return READING_IGNORABLE_RE.test(String.fromCodePoint(cp));
|
|
49
|
+
}
|
|
50
|
+
export function isReadingIgnorableForTest(cp) {
|
|
51
|
+
return isReadingIgnorable(cp);
|
|
52
|
+
}
|
|
53
|
+
const RAW_UNIT_CLASS = (() => {
|
|
54
|
+
const table = new Uint8Array(0x10000);
|
|
55
|
+
for (let unit = 0; unit < table.length; unit++) {
|
|
56
|
+
const cls = INVISIBLE_UNIT_CLASS[unit];
|
|
57
|
+
if (cls !== 0)
|
|
58
|
+
table[unit] = cls === 2 ? RAW_WHITESPACE : RAW_CONTROL;
|
|
59
|
+
}
|
|
60
|
+
const units = [];
|
|
61
|
+
for (let c = 0; c < 0x10000; c++)
|
|
62
|
+
if (c < 0xd800 || c > 0xdfff)
|
|
63
|
+
units.push(String.fromCharCode(c));
|
|
64
|
+
for (const m of units.join("").matchAll(new RegExp(`[${READING_IGNORABLE_CLASS}]`, "gu"))) {
|
|
65
|
+
const unit = m[0].charCodeAt(0);
|
|
66
|
+
if (table[unit] === 0)
|
|
67
|
+
table[unit] = RAW_IGNORABLE;
|
|
68
|
+
}
|
|
69
|
+
return table;
|
|
55
70
|
})();
|
|
71
|
+
const ASTRAL_IGNORABLE_MEMO = new Map();
|
|
72
|
+
function astralIgnorableAt(cp) {
|
|
73
|
+
let hit = ASTRAL_IGNORABLE_MEMO.get(cp);
|
|
74
|
+
if (hit === undefined) {
|
|
75
|
+
hit = isReadingIgnorable(cp);
|
|
76
|
+
if (ASTRAL_IGNORABLE_MEMO.size < 4096)
|
|
77
|
+
ASTRAL_IGNORABLE_MEMO.set(cp, hit);
|
|
78
|
+
}
|
|
79
|
+
return hit;
|
|
80
|
+
}
|
|
56
81
|
function collectRawControlCuts(s, allowed) {
|
|
57
82
|
const cuts = [];
|
|
58
83
|
let present = 0;
|
|
59
|
-
if ((allowed & (RAW_CONTROL | RAW_WHITESPACE)) === 0)
|
|
84
|
+
if ((allowed & (RAW_CONTROL | RAW_WHITESPACE | RAW_IGNORABLE)) === 0)
|
|
60
85
|
return { cuts, present };
|
|
61
|
-
|
|
62
|
-
for (let
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
86
|
+
const n = s.length;
|
|
87
|
+
for (let i = 0; i < n; i++) {
|
|
88
|
+
const unit = s.charCodeAt(i);
|
|
89
|
+
let cls = RAW_UNIT_CLASS[unit];
|
|
90
|
+
let len = 1;
|
|
91
|
+
if (cls === 0) {
|
|
92
|
+
if ((unit & 0xfc00) !== 0xd800 || i + 1 >= n)
|
|
93
|
+
continue;
|
|
94
|
+
const low = s.charCodeAt(i + 1);
|
|
95
|
+
if ((low & 0xfc00) !== 0xdc00)
|
|
96
|
+
continue;
|
|
97
|
+
if (!astralIgnorableAt(((unit - 0xd800) << 10) + (low - 0xdc00) + 0x10000)) {
|
|
98
|
+
i += 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
cls = RAW_IGNORABLE;
|
|
102
|
+
len = 2;
|
|
103
|
+
}
|
|
104
|
+
if ((cls & allowed) !== 0) {
|
|
105
|
+
cuts.push(i, i + len, cls);
|
|
106
|
+
present |= cls;
|
|
107
|
+
}
|
|
108
|
+
i += len - 1;
|
|
68
109
|
}
|
|
69
110
|
return { cuts, present };
|
|
70
111
|
}
|
|
@@ -83,7 +124,8 @@ function collectSpelledCuts(s) {
|
|
|
83
124
|
const cp = readSpelledCodePoint(s, body, read);
|
|
84
125
|
if (cp === ESCAPE_TRUNCATED)
|
|
85
126
|
return { cuts, present, open: i };
|
|
86
|
-
const
|
|
127
|
+
const unitClass = cp >= 0 && cp < 0x10000 ? INVISIBLE_UNIT_CLASS[cp] : 0;
|
|
128
|
+
const cls = cp < 0 ? 0 : isFormatCodePoint(cp) ? SPELLED_FORMAT : unitClass === 1 ? SPELLED_CONTROL : unitClass === 2 ? 0 : isReadingIgnorable(cp) ? SPELLED_IGNORABLE : 0;
|
|
87
129
|
if (cls !== 0) {
|
|
88
130
|
cuts.push(i, read.end, cls);
|
|
89
131
|
present |= cls;
|
|
@@ -465,6 +507,88 @@ let anyValueArm;
|
|
|
465
507
|
function anyValueArmRe() {
|
|
466
508
|
return (anyValueArm ??= new RegExp(`(?:${VALUE_ARM_BODIES.join("|")})`, "y"));
|
|
467
509
|
}
|
|
510
|
+
const SCAN_UNATTEMPTED = -1;
|
|
511
|
+
class ScanReader {
|
|
512
|
+
#t;
|
|
513
|
+
#n;
|
|
514
|
+
#reg = SCAN_UNATTEMPTED;
|
|
515
|
+
#hit = false;
|
|
516
|
+
#open;
|
|
517
|
+
#unattributed = false;
|
|
518
|
+
constructor(t) {
|
|
519
|
+
this.#t = t;
|
|
520
|
+
this.#n = t.length;
|
|
521
|
+
this.#open = t.length;
|
|
522
|
+
}
|
|
523
|
+
#mark() {
|
|
524
|
+
this.#hit = true;
|
|
525
|
+
if (this.#reg === SCAN_UNATTEMPTED) {
|
|
526
|
+
this.#unattributed = true;
|
|
527
|
+
this.#open = 0;
|
|
528
|
+
}
|
|
529
|
+
else if (this.#reg < this.#open)
|
|
530
|
+
this.#open = this.#reg;
|
|
531
|
+
}
|
|
532
|
+
charCodeAt(i) {
|
|
533
|
+
if (i < this.#n)
|
|
534
|
+
return this.#t.charCodeAt(i);
|
|
535
|
+
this.#mark();
|
|
536
|
+
return NaN;
|
|
537
|
+
}
|
|
538
|
+
atEnd(i) {
|
|
539
|
+
if (i < this.#n)
|
|
540
|
+
return false;
|
|
541
|
+
this.#mark();
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
readEnd() {
|
|
545
|
+
this.#mark();
|
|
546
|
+
return this.#n;
|
|
547
|
+
}
|
|
548
|
+
startsWith(lit, at) {
|
|
549
|
+
if (at + lit.length <= this.#n)
|
|
550
|
+
return this.#t.startsWith(lit, at);
|
|
551
|
+
for (let k = 0; at + k < this.#n; k++)
|
|
552
|
+
if (this.#t.charCodeAt(at + k) !== lit.charCodeAt(k))
|
|
553
|
+
return false;
|
|
554
|
+
this.#mark();
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
slice(a, b) {
|
|
558
|
+
if (b > this.#n)
|
|
559
|
+
this.#mark();
|
|
560
|
+
return this.#t.slice(a, b);
|
|
561
|
+
}
|
|
562
|
+
indexOf(lit, from = 0) {
|
|
563
|
+
return this.#t.indexOf(lit, from);
|
|
564
|
+
}
|
|
565
|
+
search(re, from) {
|
|
566
|
+
re.lastIndex = from;
|
|
567
|
+
return re.exec(this.#t);
|
|
568
|
+
}
|
|
569
|
+
lastIndexOf(lit) {
|
|
570
|
+
return this.#t.lastIndexOf(lit);
|
|
571
|
+
}
|
|
572
|
+
attempt(from) {
|
|
573
|
+
this.#reg = from;
|
|
574
|
+
this.#hit = false;
|
|
575
|
+
}
|
|
576
|
+
reachedEnd() {
|
|
577
|
+
return this.#hit;
|
|
578
|
+
}
|
|
579
|
+
begin() {
|
|
580
|
+
this.#reg = SCAN_UNATTEMPTED;
|
|
581
|
+
this.#hit = false;
|
|
582
|
+
}
|
|
583
|
+
get open() {
|
|
584
|
+
return this.#open;
|
|
585
|
+
}
|
|
586
|
+
get unattributed() {
|
|
587
|
+
return this.#unattributed;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
const VIEW_END = 0x3fffffff;
|
|
591
|
+
const segmentEnds = (s, i, limit) => i >= limit || s.atEnd(i);
|
|
468
592
|
const ARM_RANK = { structural: 0, keyword: 1, shape: 2, fragment: 3 };
|
|
469
593
|
let poolSpanCount = 0;
|
|
470
594
|
let poolArmCount = 0;
|
|
@@ -737,6 +861,112 @@ function deriveLiteralHead(re) {
|
|
|
737
861
|
first: unionMembers(per.map((p) => p.first)),
|
|
738
862
|
};
|
|
739
863
|
}
|
|
864
|
+
function expandHeadUnits(src, flags) {
|
|
865
|
+
if (/[iuv]/.test(flags))
|
|
866
|
+
throw new Error(`redact: head-unit expansion does not support the i/u/v flags (/${src}/${flags})`);
|
|
867
|
+
const fail = (at, why) => {
|
|
868
|
+
throw new Error(`redact: head-unit expansion cannot read ${why} at ${at} in /${src}/`);
|
|
869
|
+
};
|
|
870
|
+
const LIMIT = 4096;
|
|
871
|
+
const seqOf = (from) => {
|
|
872
|
+
let seqs = [[]];
|
|
873
|
+
let i = from;
|
|
874
|
+
while (i < src.length && src[i] !== "|" && src[i] !== ")") {
|
|
875
|
+
let atom;
|
|
876
|
+
const c = src[i];
|
|
877
|
+
if (c === "(") {
|
|
878
|
+
if (!src.startsWith("(?:", i))
|
|
879
|
+
return fail(i, "a group other than a non-capturing one");
|
|
880
|
+
const inner = altsOf(i + 3);
|
|
881
|
+
if (src[inner.next] !== ")")
|
|
882
|
+
return fail(i, "an unbalanced group");
|
|
883
|
+
atom = inner.seqs;
|
|
884
|
+
i = inner.next + 1;
|
|
885
|
+
}
|
|
886
|
+
else if (c === "[") {
|
|
887
|
+
let k = i + 1;
|
|
888
|
+
while (k < src.length && src[k] !== "]")
|
|
889
|
+
k += src[k] === "\\" ? 2 : 1;
|
|
890
|
+
if (k >= src.length)
|
|
891
|
+
return fail(i, "an unterminated character class");
|
|
892
|
+
atom = [[codeUnitMembers(src.slice(i, k + 1))]];
|
|
893
|
+
i = k + 1;
|
|
894
|
+
}
|
|
895
|
+
else if (c === "\\") {
|
|
896
|
+
const e = src[i + 1];
|
|
897
|
+
if (e === undefined || !(HEAD_CLASS_ESCAPES.has(e) || HEAD_LITERAL_ESCAPES.has(e)))
|
|
898
|
+
return fail(i, "an escape that is not one code unit");
|
|
899
|
+
atom = [[codeUnitMembers(src.slice(i, i + 2))]];
|
|
900
|
+
i += 2;
|
|
901
|
+
}
|
|
902
|
+
else if (c === "." || c === "^" || c === "$" || c === "*" || c === "+" || c === "?" || c === "{") {
|
|
903
|
+
return fail(i, JSON.stringify(c));
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
atom = [[codeUnitMembers(c)]];
|
|
907
|
+
i += 1;
|
|
908
|
+
}
|
|
909
|
+
let lo = 1;
|
|
910
|
+
let hi = 1;
|
|
911
|
+
if (src[i] === "?") {
|
|
912
|
+
lo = 0;
|
|
913
|
+
i += 1;
|
|
914
|
+
}
|
|
915
|
+
else if (src[i] === "{") {
|
|
916
|
+
const m = /^\{(\d+)(?:,(\d+))?\}/.exec(src.slice(i));
|
|
917
|
+
if (m === null)
|
|
918
|
+
return fail(i, "an unbounded quantifier");
|
|
919
|
+
lo = Number(m[1]);
|
|
920
|
+
hi = m[2] === undefined ? lo : Number(m[2]);
|
|
921
|
+
i += m[0].length;
|
|
922
|
+
}
|
|
923
|
+
else if (src[i] === "*" || src[i] === "+")
|
|
924
|
+
return fail(i, "an unbounded quantifier");
|
|
925
|
+
let reps = [];
|
|
926
|
+
let power = [[]];
|
|
927
|
+
for (let k = 0; k <= hi; k++) {
|
|
928
|
+
if (k >= lo)
|
|
929
|
+
reps = reps.concat(power);
|
|
930
|
+
if (k < hi)
|
|
931
|
+
power = power.flatMap((p) => atom.map((a) => [...p, ...a]));
|
|
932
|
+
}
|
|
933
|
+
seqs = seqs.flatMap((s) => reps.map((r) => [...s, ...r]));
|
|
934
|
+
if (seqs.length > LIMIT)
|
|
935
|
+
return fail(i, "a head with too many spellings");
|
|
936
|
+
}
|
|
937
|
+
return { seqs, next: i };
|
|
938
|
+
};
|
|
939
|
+
const altsOf = (from) => {
|
|
940
|
+
const seqs = [];
|
|
941
|
+
let i = from;
|
|
942
|
+
for (;;) {
|
|
943
|
+
const one = seqOf(i);
|
|
944
|
+
seqs.push(...one.seqs);
|
|
945
|
+
i = one.next;
|
|
946
|
+
if (src[i] !== "|")
|
|
947
|
+
break;
|
|
948
|
+
i += 1;
|
|
949
|
+
}
|
|
950
|
+
return { seqs, next: i };
|
|
951
|
+
};
|
|
952
|
+
const all = altsOf(0);
|
|
953
|
+
if (all.next !== src.length)
|
|
954
|
+
return fail(all.next, "trailing syntax");
|
|
955
|
+
if (all.seqs.some((s) => s.length === 0))
|
|
956
|
+
return fail(0, "an empty head spelling (every position would be feasible)");
|
|
957
|
+
return all.seqs;
|
|
958
|
+
}
|
|
959
|
+
function headFeasibleAt(seqs, text, p) {
|
|
960
|
+
const room = text.length - p;
|
|
961
|
+
outer: for (const seq of seqs) {
|
|
962
|
+
const m = Math.min(seq.length, room);
|
|
963
|
+
for (let k = 0; k < m; k++)
|
|
964
|
+
if (unitBit(seq[k], text.charCodeAt(p + k)) === 0)
|
|
965
|
+
continue outer;
|
|
966
|
+
return true;
|
|
967
|
+
}
|
|
968
|
+
return false;
|
|
969
|
+
}
|
|
740
970
|
const repeatLen = (k, len) => (k === 0 ? 0 : k * len);
|
|
741
971
|
function readReachAlternatives(src, from) {
|
|
742
972
|
const alts = [];
|
|
@@ -921,17 +1151,56 @@ function resolveSpanOverlaps(spans) {
|
|
|
921
1151
|
}
|
|
922
1152
|
return kept;
|
|
923
1153
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
let
|
|
1154
|
+
const NO_JOINTS = Object.freeze([]);
|
|
1155
|
+
const sortedJoints = (joints) => [...new Set(joints)].sort((a, b) => a - b);
|
|
1156
|
+
function firstJointAfter(at, start) {
|
|
1157
|
+
let lo = 0;
|
|
1158
|
+
let hi = at.length;
|
|
1159
|
+
while (lo < hi) {
|
|
1160
|
+
const mid = (lo + hi) >>> 1;
|
|
1161
|
+
if (at[mid] <= start)
|
|
1162
|
+
lo = mid + 1;
|
|
1163
|
+
else
|
|
1164
|
+
hi = mid;
|
|
1165
|
+
}
|
|
1166
|
+
return lo;
|
|
1167
|
+
}
|
|
1168
|
+
function jointsCrossedBy(spans, joints) {
|
|
1169
|
+
if (joints.length === 0)
|
|
1170
|
+
return [];
|
|
1171
|
+
const at = sortedJoints(joints);
|
|
1172
|
+
const crossed = new Set();
|
|
1173
|
+
for (const s of spans)
|
|
1174
|
+
for (let i = firstJointAfter(at, s.start); i < at.length && at[i] < s.end; i++)
|
|
1175
|
+
crossed.add(at[i]);
|
|
1176
|
+
return [...crossed].sort((a, b) => a - b);
|
|
1177
|
+
}
|
|
1178
|
+
function cutAtJoints(spans, joints) {
|
|
1179
|
+
const at = sortedJoints(joints);
|
|
1180
|
+
const out = [];
|
|
929
1181
|
for (const s of spans) {
|
|
930
|
-
|
|
931
|
-
|
|
1182
|
+
let start = s.start;
|
|
1183
|
+
for (let i = firstJointAfter(at, s.start); i < at.length && at[i] < s.end; i++) {
|
|
1184
|
+
out.push({ ...s, start, end: at[i] });
|
|
1185
|
+
start = at[i];
|
|
1186
|
+
}
|
|
1187
|
+
out.push(start === s.start ? s : { ...s, start });
|
|
932
1188
|
}
|
|
933
|
-
|
|
934
|
-
|
|
1189
|
+
return out;
|
|
1190
|
+
}
|
|
1191
|
+
const poolTie = (a, b) => a.rank - b.rank || a.order - b.order;
|
|
1192
|
+
export function mergeRedactionSpans(spans, tie = () => 0, joints = NO_JOINTS) {
|
|
1193
|
+
const order = (joints.length === 0 ? [...spans] : cutAtJoints(spans, joints)).sort((a, b) => a.start - b.start || b.end - a.end || tie(a, b));
|
|
1194
|
+
const committed = joints.length === 0 ? undefined : new Set(joints);
|
|
1195
|
+
const out = [];
|
|
1196
|
+
for (const s of order) {
|
|
1197
|
+
const last = out[out.length - 1];
|
|
1198
|
+
if (last === undefined || s.start > last.end || (s.start === last.end && committed?.has(s.start) === true))
|
|
1199
|
+
out.push(s);
|
|
1200
|
+
else if (s.end > last.end)
|
|
1201
|
+
out[out.length - 1] = { ...last, end: s.end };
|
|
1202
|
+
}
|
|
1203
|
+
return out;
|
|
935
1204
|
}
|
|
936
1205
|
function collectValueArmSpans(arm, text, out) {
|
|
937
1206
|
const { g, y, back, repl, rank, order } = arm;
|
|
@@ -1070,14 +1339,9 @@ const CREDENTIAL_NAME_ANCHORS = {
|
|
|
1070
1339
|
"x-amz-signature": "declarative", "x-amz-security-token": "declarative", "x-amz-credential": "declarative",
|
|
1071
1340
|
sas: "structure-only",
|
|
1072
1341
|
};
|
|
1073
|
-
const CREDENTIAL_NAME_ALT = (() => {
|
|
1074
|
-
for (const w of CREDENTIAL_PARAM_NAMES) {
|
|
1075
|
-
if (!/^[a-z][a-z0-9_-]*$/.test(w))
|
|
1076
|
-
throw new Error(`redact: credential name ${JSON.stringify(w)} must be lowercase [a-z0-9_-] (the alternation is built without escaping)`);
|
|
1077
|
-
}
|
|
1078
|
-
return [...CREDENTIAL_PARAM_NAMES].sort((a, b) => b.length - a.length || (a < b ? -1 : 1)).join("|");
|
|
1079
|
-
})();
|
|
1080
1342
|
const CREDENTIAL_NAME_MAX = Math.max(...CREDENTIAL_PARAM_NAMES.map((w) => w.length));
|
|
1343
|
+
const JSON_FIELD_NAME_CLASS = "[A-Za-z0-9_.-]";
|
|
1344
|
+
const isJsonFieldNameCode = (c) => isAsciiAlnumCode(c) || c === CH_UNDERSCORE || c === CH_MINUS || c === CH_DOT;
|
|
1081
1345
|
const JSON_FIELD_QUOTE_FORMS = ['"', '\\"', '\\\\\\"'];
|
|
1082
1346
|
for (let d = 0; d < JSON_FIELD_QUOTE_FORMS.length; d++) {
|
|
1083
1347
|
if (JSON_FIELD_QUOTE_FORMS[d] !== "\\".repeat(2 ** d - 1) + '"')
|
|
@@ -1096,15 +1360,26 @@ function buildJsonSecretFieldSource() {
|
|
|
1096
1360
|
q = b + q;
|
|
1097
1361
|
b = b + b;
|
|
1098
1362
|
}
|
|
1099
|
-
alts.push(String.raw `(${q}(
|
|
1363
|
+
alts.push(String.raw `(${q}(${JSON_FIELD_NAME_CLASS}+)${q}\s*:\s*)${q}(?:${o}|${l}|${b}(?:${o}|${b}|${q}))*${q}`);
|
|
1100
1364
|
}
|
|
1101
1365
|
return alts.join("|");
|
|
1102
1366
|
}
|
|
1103
1367
|
const asciiLower = (s) => s.replace(/[A-Z]/g, (c) => c.toLowerCase());
|
|
1104
1368
|
function credentialNameAnchor(name) {
|
|
1105
|
-
|
|
1369
|
+
let word = CREDENTIAL_WORD_MEMO.get(name);
|
|
1370
|
+
if (word === undefined) {
|
|
1371
|
+
word = credentialParamWordOf(name) ?? null;
|
|
1372
|
+
if (name.length <= CREDENTIAL_WORD_MEMO_NAME_MAX) {
|
|
1373
|
+
if (CREDENTIAL_WORD_MEMO.size >= CREDENTIAL_WORD_MEMO_SIZE)
|
|
1374
|
+
CREDENTIAL_WORD_MEMO.clear();
|
|
1375
|
+
CREDENTIAL_WORD_MEMO.set(name, word);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
return word === null ? undefined : CREDENTIAL_NAME_ANCHORS[word];
|
|
1106
1379
|
}
|
|
1107
|
-
const
|
|
1380
|
+
const CREDENTIAL_WORD_MEMO = new Map();
|
|
1381
|
+
const CREDENTIAL_WORD_MEMO_SIZE = 1024;
|
|
1382
|
+
const CREDENTIAL_WORD_MEMO_NAME_MAX = 64;
|
|
1108
1383
|
const BARE_WORD_READINGS = {
|
|
1109
1384
|
null: "absent-or-boolean", nil: "absent-or-boolean", none: "absent-or-boolean", undefined: "absent-or-boolean",
|
|
1110
1385
|
true: "absent-or-boolean", false: "absent-or-boolean", yes: "absent-or-boolean", no: "absent-or-boolean",
|
|
@@ -1157,7 +1432,7 @@ const SHAPE_SECRET_PATTERNS = [
|
|
|
1157
1432
|
[new RegExp(String.raw `xox[baprs]-${atLeast("[A-Za-z0-9-]", 10)}`, "g"), "«redacted:slack-token»"],
|
|
1158
1433
|
[new RegExp(String.raw `AKIA${atLeast("[0-9A-Z]", 16)}`, "g"), "«redacted:aws-key»"],
|
|
1159
1434
|
[new RegExp(String.raw `ASIA${atLeast("[0-9A-Z]", 16)}`, "g"), "«redacted:aws-key»"],
|
|
1160
|
-
[new RegExp(String.raw `(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-${atLeast("[A-Za-z0-9_-]", 20)}|(?:sk|rk)_(?:live|test|org)_${atLeast("[A-Za-z0-9]", 24)}|pypi-${atLeast("[A-Za-z0-9_-]", 85)})`, "g"), "«redacted:key»"],
|
|
1435
|
+
[new RegExp(String.raw `(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-${atLeast("[A-Za-z0-9_-]", 20)}|(?:sk|rk)_(?:live|test|org)_${atLeast("[A-Za-z0-9]", 24)}|pypi-${atLeast("[A-Za-z0-9_-]", 85)}|(?<![A-Za-z0-9])(?:npm_${atLeast("[A-Za-z0-9]", 36)}|hf_${atLeast("[A-Za-z0-9]", 34)}|ya29\.${atLeast("[A-Za-z0-9._-]", 30)}))`, "g"), "«redacted:key»"],
|
|
1161
1436
|
[new RegExp(String.raw `xapp-\d-${atLeast("[A-Za-z0-9-]", 20)}`, "g"), "«redacted:slack-token»"],
|
|
1162
1437
|
[valueArm("sk-", "[A-Za-z0-9_-]", SK_FULL_ARM_MIN, "self-evident"), "«redacted:key»"],
|
|
1163
1438
|
];
|
|
@@ -1170,16 +1445,16 @@ const isIdentStartCode = (c) => (c >= CH_A && c <= CH_Z) || (c >= CH_a && c <= C
|
|
|
1170
1445
|
const isIdentCode = (c) => isIdentStartCode(c) || (c >= CH_0 && c <= CH_9) || c === CH_UNDERSCORE || c === CH_MINUS;
|
|
1171
1446
|
function pemEscapeLetterAt(s, i, limit) {
|
|
1172
1447
|
let j = i;
|
|
1173
|
-
while (j
|
|
1448
|
+
while (!segmentEnds(s, j, limit) && s.charCodeAt(j) === CH_BACKSLASH)
|
|
1174
1449
|
j += 1;
|
|
1175
|
-
if (j === i || j
|
|
1450
|
+
if (j === i || segmentEnds(s, j, limit))
|
|
1176
1451
|
return -1;
|
|
1177
1452
|
const n = s.charCodeAt(j);
|
|
1178
1453
|
return n === CH_r || n === CH_n || n === CH_t ? j : -1;
|
|
1179
1454
|
}
|
|
1180
1455
|
function skipPemSeps(scan, s, i, limit) {
|
|
1181
1456
|
for (;;) {
|
|
1182
|
-
if (i
|
|
1457
|
+
if (segmentEnds(s, i, limit))
|
|
1183
1458
|
return i;
|
|
1184
1459
|
if (tokenEnd(scan, i) >= 0)
|
|
1185
1460
|
return i;
|
|
@@ -1199,7 +1474,7 @@ function skipPemSeps(scan, s, i, limit) {
|
|
|
1199
1474
|
}
|
|
1200
1475
|
}
|
|
1201
1476
|
function pemLineBreakLen(s, i, limit) {
|
|
1202
|
-
if (i
|
|
1477
|
+
if (segmentEnds(s, i, limit))
|
|
1203
1478
|
return 0;
|
|
1204
1479
|
const c = s.charCodeAt(i);
|
|
1205
1480
|
if (c === CH_CR || c === CH_LF)
|
|
@@ -1212,7 +1487,7 @@ function pemLineBreakLen(s, i, limit) {
|
|
|
1212
1487
|
return 0;
|
|
1213
1488
|
}
|
|
1214
1489
|
function pemInlineSepLen(s, i, limit) {
|
|
1215
|
-
if (i
|
|
1490
|
+
if (segmentEnds(s, i, limit))
|
|
1216
1491
|
return 0;
|
|
1217
1492
|
const c = s.charCodeAt(i);
|
|
1218
1493
|
if (c === CH_SPACE || c === CH_TAB)
|
|
@@ -1225,16 +1500,20 @@ function pemInlineSepLen(s, i, limit) {
|
|
|
1225
1500
|
return 0;
|
|
1226
1501
|
}
|
|
1227
1502
|
function probePemHeaderToken(scan, s, p, limit) {
|
|
1228
|
-
if (
|
|
1503
|
+
if (segmentEnds(s, p, limit))
|
|
1504
|
+
return -1;
|
|
1505
|
+
if (tokenEnd(scan, p) >= 0 || !isIdentStartCode(s.charCodeAt(p)))
|
|
1229
1506
|
return -1;
|
|
1230
1507
|
p += 1;
|
|
1231
1508
|
let identLen = 1;
|
|
1232
|
-
while (identLen < PEM_HEADER_IDENT_MAX && p
|
|
1509
|
+
while (identLen < PEM_HEADER_IDENT_MAX && !segmentEnds(s, p, limit) && tokenEnd(scan, p) < 0 && isIdentCode(s.charCodeAt(p))) {
|
|
1233
1510
|
p += 1;
|
|
1234
1511
|
identLen += 1;
|
|
1235
1512
|
}
|
|
1236
1513
|
for (;;) {
|
|
1237
|
-
if (
|
|
1514
|
+
if (segmentEnds(s, p, limit))
|
|
1515
|
+
return -1;
|
|
1516
|
+
if (tokenEnd(scan, p) >= 0)
|
|
1238
1517
|
return -1;
|
|
1239
1518
|
const c = s.charCodeAt(p);
|
|
1240
1519
|
if (c === CH_SPACE || c === CH_TAB) {
|
|
@@ -1255,7 +1534,7 @@ function setPemHdr(scan, search, contentEnd, next, hitLimit, jsonEnd = false) {
|
|
|
1255
1534
|
}
|
|
1256
1535
|
function parsePemHeaderLine(scan, s, i, limit, allowBare, json) {
|
|
1257
1536
|
const start = skipPemSeps(scan, s, i, limit);
|
|
1258
|
-
if (start
|
|
1537
|
+
if (segmentEnds(s, start, limit))
|
|
1259
1538
|
return false;
|
|
1260
1539
|
const afterToken = probePemHeaderToken(scan, s, start, limit);
|
|
1261
1540
|
if (afterToken < 0 && !allowBare)
|
|
@@ -1264,7 +1543,7 @@ function parsePemHeaderLine(scan, s, i, limit, allowBare, json) {
|
|
|
1264
1543
|
if (afterToken >= 0 && probePemHeaderToken(scan, s, p, limit) >= 0)
|
|
1265
1544
|
return setPemHdr(scan, start, p, p, false);
|
|
1266
1545
|
for (;;) {
|
|
1267
|
-
if (p
|
|
1546
|
+
if (segmentEnds(s, p, limit))
|
|
1268
1547
|
return setPemHdr(scan, start, p, p, true);
|
|
1269
1548
|
const unit = crossEnd(scan, p);
|
|
1270
1549
|
if (unit >= 0) {
|
|
@@ -1286,9 +1565,9 @@ function parsePemHeaderLine(scan, s, i, limit, allowBare, json) {
|
|
|
1286
1565
|
return setPemHdr(scan, start, p, p + 1, false);
|
|
1287
1566
|
if (c === CH_BACKSLASH) {
|
|
1288
1567
|
let j = p;
|
|
1289
|
-
while (j
|
|
1568
|
+
while (!segmentEnds(s, j, limit) && s.charCodeAt(j) === CH_BACKSLASH)
|
|
1290
1569
|
j += 1;
|
|
1291
|
-
const n = j
|
|
1570
|
+
const n = segmentEnds(s, j, limit) ? -1 : s.charCodeAt(j);
|
|
1292
1571
|
if (n !== CH_r && n !== CH_n && n !== CH_t) {
|
|
1293
1572
|
p = json && (j - p) % 2 === 0 && n === CH_QUOTE ? j : Math.min(limit, j + 1);
|
|
1294
1573
|
continue;
|
|
@@ -1310,7 +1589,7 @@ function parsePemHeaderLine(scan, s, i, limit, allowBare, json) {
|
|
|
1310
1589
|
break;
|
|
1311
1590
|
q += u;
|
|
1312
1591
|
}
|
|
1313
|
-
if (q
|
|
1592
|
+
if (segmentEnds(s, q, limit))
|
|
1314
1593
|
return setPemHdr(scan, start, p, q, true);
|
|
1315
1594
|
if (probePemHeaderToken(scan, s, q, limit) >= 0)
|
|
1316
1595
|
return setPemHdr(scan, start, p, q, false);
|
|
@@ -1323,7 +1602,7 @@ function parsePemBody(scan, s, i, limit) {
|
|
|
1323
1602
|
for (;;) {
|
|
1324
1603
|
const q = skipPemSeps(scan, s, p, limit);
|
|
1325
1604
|
let r = q;
|
|
1326
|
-
while (r
|
|
1605
|
+
while (!segmentEnds(s, r, limit) && tokenEnd(scan, r) < 0 && isBase64Code(s.charCodeAt(r)))
|
|
1327
1606
|
r += 1;
|
|
1328
1607
|
if (r - q < PEM_BODY_RUN_MIN)
|
|
1329
1608
|
break;
|
|
@@ -1433,13 +1712,24 @@ function findPemFence(scan, text, from) {
|
|
|
1433
1712
|
}
|
|
1434
1713
|
const SSH2_FENCE_OPEN = "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----";
|
|
1435
1714
|
const SSH2_FENCE_CLOSE = "---- END SSH2 ENCRYPTED PRIVATE KEY ----";
|
|
1436
|
-
const
|
|
1715
|
+
const ARMOR_BODY_MAX = (() => {
|
|
1716
|
+
const caps = STRUCTURAL_SECRET_PATTERNS.flatMap(([re]) => {
|
|
1717
|
+
const m = /\[\\s\\S\]\{0,(\d+)\}\?/.exec(re.source);
|
|
1718
|
+
return m === null ? [] : [Number(m[1])];
|
|
1719
|
+
});
|
|
1720
|
+
const first = caps[0];
|
|
1721
|
+
if (caps.length !== 2 || first === undefined || caps.some((c) => c !== first)) {
|
|
1722
|
+
throw new Error(`redact: the PEM and SSH2 armor rows of the structural table must each declare one body cap of the same size (read ${JSON.stringify(caps)})`);
|
|
1723
|
+
}
|
|
1724
|
+
return first;
|
|
1725
|
+
})();
|
|
1726
|
+
export const MAX_RECOGNITION_SPAN = SSH2_FENCE_OPEN.length + ARMOR_BODY_MAX + SSH2_FENCE_CLOSE.length;
|
|
1437
1727
|
function armorCloseAt(scan, text, kind, bodyFrom, max) {
|
|
1438
|
-
const near = firstDelim(scan,
|
|
1728
|
+
const near = firstDelim(scan, kind, bodyFrom, false);
|
|
1439
1729
|
if (near < 0)
|
|
1440
1730
|
return -1;
|
|
1441
|
-
const free = firstDelim(scan,
|
|
1442
|
-
const far = free >= 0 ? free : lastNotHiddenDelim(scan,
|
|
1731
|
+
const free = firstDelim(scan, kind, bodyFrom, true);
|
|
1732
|
+
const far = free >= 0 ? free : lastNotHiddenDelim(scan, kind, near, VIEW_END);
|
|
1443
1733
|
if (far > near && blockWithin(scan, text, kind, bodyFrom, far, max))
|
|
1444
1734
|
return far;
|
|
1445
1735
|
return blockWithin(scan, text, kind, bodyFrom, near, max) ? near : -1;
|
|
@@ -1453,8 +1743,8 @@ function blockWithin(scan, text, kind, bodyFrom, close, max) {
|
|
|
1453
1743
|
}
|
|
1454
1744
|
function collectSsh2FenceSpans(scan, text, json, span, isHead) {
|
|
1455
1745
|
const fam = familyCode("ssh2-armor");
|
|
1456
|
-
const opens = delimPositions(scan,
|
|
1457
|
-
const closes = delimPositions(scan,
|
|
1746
|
+
const opens = delimPositions(scan, "ssh2-open");
|
|
1747
|
+
const closes = delimPositions(scan, "ssh2-close");
|
|
1458
1748
|
const blockEnds = [];
|
|
1459
1749
|
let firstLive = 0;
|
|
1460
1750
|
let freshFrom = -1;
|
|
@@ -1469,13 +1759,13 @@ function collectSsh2FenceSpans(scan, text, json, span, isHead) {
|
|
|
1469
1759
|
}
|
|
1470
1760
|
if (rooted && prevEnd >= 0) {
|
|
1471
1761
|
scan.self = readingKey(fam, c);
|
|
1472
|
-
while (firstLive < blockEnds.length && uncoveredWithin(scan, blockEnds[firstLive], c + SSH2_FENCE_CLOSE.length) >
|
|
1762
|
+
while (firstLive < blockEnds.length && uncoveredWithin(scan, blockEnds[firstLive], c + SSH2_FENCE_CLOSE.length) > ARMOR_BODY_MAX + SSH2_FENCE_CLOSE.length)
|
|
1473
1763
|
firstLive += 1;
|
|
1474
1764
|
for (let j = firstLive; j < blockEnds.length; j++) {
|
|
1475
1765
|
const from = blockEnds[j];
|
|
1476
1766
|
if (from > c)
|
|
1477
1767
|
break;
|
|
1478
|
-
if ((from === freshFrom && blockWithin(scan, text, "ssh2-close", freshEnd, c,
|
|
1768
|
+
if ((from === freshFrom && blockWithin(scan, text, "ssh2-close", freshEnd, c, ARMOR_BODY_MAX - 1)) || blockWithin(scan, text, "ssh2-close", from, c, ARMOR_BODY_MAX)) {
|
|
1479
1769
|
span(from, c + SSH2_FENCE_CLOSE.length, c, NOT_CLOSED);
|
|
1480
1770
|
freshFrom = from;
|
|
1481
1771
|
freshEnd = c + SSH2_FENCE_CLOSE.length;
|
|
@@ -1500,7 +1790,7 @@ function collectSsh2FenceSpans(scan, text, json, span, isHead) {
|
|
|
1500
1790
|
openAt = k < opens.length ? opens[k] : -1;
|
|
1501
1791
|
return openAt;
|
|
1502
1792
|
};
|
|
1503
|
-
const truncatedEnd = createTruncatedBlockEnd(scan, text, json, (from) => firstDelim(scan,
|
|
1793
|
+
const truncatedEnd = createTruncatedBlockEnd(scan, text, json, (from) => firstDelim(scan, "ssh2-close", from, true));
|
|
1504
1794
|
for (let oi = 0; oi < opens.length;) {
|
|
1505
1795
|
const fence = opens[oi];
|
|
1506
1796
|
const bodyFrom = fence + SSH2_FENCE_OPEN.length;
|
|
@@ -1509,30 +1799,31 @@ function collectSsh2FenceSpans(scan, text, json, span, isHead) {
|
|
|
1509
1799
|
continue;
|
|
1510
1800
|
}
|
|
1511
1801
|
scan.self = readingKey(fam, fence);
|
|
1512
|
-
|
|
1513
|
-
|
|
1802
|
+
text.attempt(fence);
|
|
1803
|
+
if (isHead && measureWithin(scan, bodyFrom, text.readEnd(), ARMOR_BODY_MAX)) {
|
|
1804
|
+
span(fence, text.readEnd(), fence, NOT_CLOSED, true);
|
|
1514
1805
|
return;
|
|
1515
1806
|
}
|
|
1516
1807
|
let resume = fence + 1;
|
|
1517
1808
|
if (!isHead) {
|
|
1518
1809
|
const open = nextFreeOpen(bodyFrom);
|
|
1519
|
-
const limit = open < 0 ?
|
|
1810
|
+
const limit = open < 0 ? VIEW_END : open;
|
|
1520
1811
|
const readEnd = (crossEndsRun) => {
|
|
1521
1812
|
const t = truncatedEnd(bodyFrom, limit, crossEndsRun);
|
|
1522
1813
|
const bodyEnd = t < 0 ? -1 : armorBodyEnd(scan, text, json, bodyFrom, limit, false, crossEndsRun);
|
|
1523
1814
|
return bodyEnd < 0 ? -1 : Math.max(bodyEnd, t);
|
|
1524
1815
|
};
|
|
1525
1816
|
const far = readEnd(false);
|
|
1526
|
-
const near = far >= 0 && !measureWithin(scan, bodyFrom, far,
|
|
1817
|
+
const near = far >= 0 && !measureWithin(scan, bodyFrom, far, ARMOR_BODY_MAX) ? readEnd(true) : -1;
|
|
1527
1818
|
const end = near >= 0 && near < far ? near : far;
|
|
1528
|
-
if (end >= 0 && measureWithin(scan, bodyFrom, end,
|
|
1819
|
+
if (end >= 0 && measureWithin(scan, bodyFrom, end, ARMOR_BODY_MAX)) {
|
|
1529
1820
|
span(fence, end, fence, NOT_CLOSED);
|
|
1530
1821
|
resume = end;
|
|
1531
1822
|
}
|
|
1532
1823
|
}
|
|
1533
|
-
const close = armorCloseAt(scan, text, "ssh2-close", bodyFrom,
|
|
1824
|
+
const close = armorCloseAt(scan, text, "ssh2-close", bodyFrom, ARMOR_BODY_MAX);
|
|
1534
1825
|
if (close < 0) {
|
|
1535
|
-
if (isHead && firstDelim(scan,
|
|
1826
|
+
if (isHead && firstDelim(scan, "ssh2-close", bodyFrom, false) < 0)
|
|
1536
1827
|
return;
|
|
1537
1828
|
oi = lowerBound(opens, resume);
|
|
1538
1829
|
continue;
|
|
@@ -1543,16 +1834,16 @@ function collectSsh2FenceSpans(scan, text, json, span, isHead) {
|
|
|
1543
1834
|
}
|
|
1544
1835
|
}
|
|
1545
1836
|
const PEM_END_OPEN = "-----END";
|
|
1546
|
-
const PEM_FENCE_BODY_MAX = 8192;
|
|
1547
1837
|
const PEM_LINE_INVALID = -1;
|
|
1548
1838
|
const PEM_LINE_OPEN = -2;
|
|
1549
1839
|
function pemFenceLineEnd(text, labelFrom) {
|
|
1550
1840
|
const close = text.indexOf(PEM_FENCE_CLOSE, labelFrom);
|
|
1551
1841
|
if (close < 0) {
|
|
1552
|
-
|
|
1842
|
+
const n = text.readEnd();
|
|
1843
|
+
let to = n;
|
|
1553
1844
|
while (to > labelFrom && text.charCodeAt(to - 1) === 45)
|
|
1554
1845
|
to -= 1;
|
|
1555
|
-
const stillPossible =
|
|
1846
|
+
const stillPossible = n - to >= 2 ? isPemFenceLabel(text, labelFrom, to) : !pemLabelDashRuleBroken(text, labelFrom, to);
|
|
1556
1847
|
return stillPossible ? PEM_LINE_OPEN : PEM_LINE_INVALID;
|
|
1557
1848
|
}
|
|
1558
1849
|
return isPemFenceLabel(text, labelFrom, close) ? close + PEM_FENCE_CLOSE.length : PEM_LINE_INVALID;
|
|
@@ -1563,23 +1854,24 @@ function collectPemFenceSpans(scan, text, span, isHead) {
|
|
|
1563
1854
|
const fence = text.indexOf(PEM_FENCE_OPEN, from);
|
|
1564
1855
|
if (fence < 0)
|
|
1565
1856
|
return;
|
|
1857
|
+
text.attempt(fence);
|
|
1566
1858
|
const bodyFrom = pemFenceLineEnd(text, fence + PEM_FENCE_OPEN.length);
|
|
1567
1859
|
if (bodyFrom === PEM_LINE_INVALID) {
|
|
1568
1860
|
from = fence + 1;
|
|
1569
1861
|
continue;
|
|
1570
1862
|
}
|
|
1571
|
-
if (lineHeld(scan, fence, bodyFrom === PEM_LINE_OPEN ? text.
|
|
1863
|
+
if (lineHeld(scan, fence, bodyFrom === PEM_LINE_OPEN ? text.readEnd() : bodyFrom, readingKey(fam, fence))) {
|
|
1572
1864
|
from = fence + 1;
|
|
1573
1865
|
continue;
|
|
1574
1866
|
}
|
|
1575
1867
|
scan.self = readingKey(fam, fence);
|
|
1576
|
-
const near = bodyFrom === PEM_LINE_OPEN ? -1 : firstDelim(scan,
|
|
1577
|
-
if (near < 0 || (isHead && firstDelim(scan,
|
|
1868
|
+
const near = bodyFrom === PEM_LINE_OPEN ? -1 : firstDelim(scan, "pem-end", bodyFrom, false);
|
|
1869
|
+
if (near < 0 || (isHead && firstDelim(scan, "pem-end", bodyFrom, true) < 0)) {
|
|
1578
1870
|
if (isHead)
|
|
1579
|
-
span(fence, text.
|
|
1871
|
+
span(fence, text.readEnd(), fence, NOT_CLOSED, true);
|
|
1580
1872
|
return;
|
|
1581
1873
|
}
|
|
1582
|
-
const endAt = armorCloseAt(scan, text, "pem-end", bodyFrom,
|
|
1874
|
+
const endAt = armorCloseAt(scan, text, "pem-end", bodyFrom, ARMOR_BODY_MAX);
|
|
1583
1875
|
if (endAt < 0) {
|
|
1584
1876
|
from = fence + 1;
|
|
1585
1877
|
continue;
|
|
@@ -1591,8 +1883,8 @@ function collectPemFenceSpans(scan, text, span, isHead) {
|
|
|
1591
1883
|
}
|
|
1592
1884
|
function truncationWindowEnd(text, from, json) {
|
|
1593
1885
|
if (!json)
|
|
1594
|
-
return text.
|
|
1595
|
-
for (let i = from;
|
|
1886
|
+
return text.readEnd();
|
|
1887
|
+
for (let i = from; !text.atEnd(i); i++) {
|
|
1596
1888
|
const c = text.charCodeAt(i);
|
|
1597
1889
|
if (c === CH_BACKSLASH) {
|
|
1598
1890
|
i += 1;
|
|
@@ -1601,7 +1893,7 @@ function truncationWindowEnd(text, from, json) {
|
|
|
1601
1893
|
if (c === CH_QUOTE)
|
|
1602
1894
|
return i;
|
|
1603
1895
|
}
|
|
1604
|
-
return text.
|
|
1896
|
+
return text.readEnd();
|
|
1605
1897
|
}
|
|
1606
1898
|
function armorBodyEnd(scan, text, json, from, limit, allowBare, crossEndsRun) {
|
|
1607
1899
|
let pos = from;
|
|
@@ -1643,13 +1935,19 @@ function collectPemFragmentSpans(scan, text, json, span, isHead) {
|
|
|
1643
1935
|
const fam = familyCode("pem-armor");
|
|
1644
1936
|
let cur = findPemFence(scan, text, 0);
|
|
1645
1937
|
let inherited = false;
|
|
1646
|
-
const truncatedEnd = createTruncatedBlockEnd(scan, text, json, (from) => firstDelim(scan,
|
|
1938
|
+
const truncatedEnd = createTruncatedBlockEnd(scan, text, json, (from) => firstDelim(scan, "pem-end", from, true));
|
|
1647
1939
|
while (cur !== undefined) {
|
|
1648
1940
|
const next = findPemFence(scan, text, cur.after);
|
|
1649
|
-
const limit = next === undefined ?
|
|
1941
|
+
const limit = next === undefined ? VIEW_END : next.fence;
|
|
1650
1942
|
scan.self = readingKey(fam, cur.fence);
|
|
1943
|
+
text.attempt(cur.fence);
|
|
1651
1944
|
const bodyEnd = armorBodyEnd(scan, text, json, cur.after, limit, inherited, false);
|
|
1652
1945
|
inherited = scan.hdr.hitLimit;
|
|
1946
|
+
if (isHead && text.reachedEnd()) {
|
|
1947
|
+
span(cur.fence, text.readEnd(), cur.fence, NOT_CLOSED, bodyEnd < 0);
|
|
1948
|
+
cur = next;
|
|
1949
|
+
continue;
|
|
1950
|
+
}
|
|
1653
1951
|
const end = isHead || bodyEnd < 0 ? bodyEnd : Math.max(bodyEnd, truncatedEnd(cur.after, limit, false));
|
|
1654
1952
|
if (end >= 0)
|
|
1655
1953
|
span(cur.fence, end, cur.fence, NOT_CLOSED);
|
|
@@ -1658,22 +1956,21 @@ function collectPemFragmentSpans(scan, text, json, span, isHead) {
|
|
|
1658
1956
|
}
|
|
1659
1957
|
function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
1660
1958
|
const KEY = PPK_LINES_FIELD;
|
|
1661
|
-
const n = text.length;
|
|
1662
1959
|
const LINE_NONE = -1;
|
|
1663
1960
|
const LINE_OPEN = -2;
|
|
1664
1961
|
const openAt = (i) => {
|
|
1665
1962
|
if (!isHead)
|
|
1666
1963
|
return false;
|
|
1667
1964
|
let k = i;
|
|
1668
|
-
while (k
|
|
1965
|
+
while (!text.atEnd(k) && tokenEnd(scan, k) < 0 && text.charCodeAt(k) === 92)
|
|
1669
1966
|
k += 1;
|
|
1670
|
-
return k
|
|
1967
|
+
return text.atEnd(k);
|
|
1671
1968
|
};
|
|
1672
1969
|
const isB64 = (c) => (c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 43 || c === 47 || c === 61;
|
|
1673
1970
|
const b64At = (i) => tokenEnd(scan, i) < 0 && isB64(text.charCodeAt(i));
|
|
1674
|
-
const skipHs = (i) => { while (i
|
|
1971
|
+
const skipHs = (i) => { while (!text.atEnd(i) && tokenEnd(scan, i) < 0 && (text.charCodeAt(i) === 32 || text.charCodeAt(i) === 9))
|
|
1675
1972
|
i += 1; return i; };
|
|
1676
|
-
const lineEndHidden = (i) => i
|
|
1973
|
+
const lineEndHidden = (i) => !text.atEnd(i) && delimClass(scan, i) === DELIM_HIDDEN;
|
|
1677
1974
|
const skipNewlines = (i) => {
|
|
1678
1975
|
let q = skipHs(i);
|
|
1679
1976
|
let seen = false;
|
|
@@ -1716,7 +2013,7 @@ function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
|
1716
2013
|
if (lineEndHidden(i))
|
|
1717
2014
|
return 0;
|
|
1718
2015
|
let k = i;
|
|
1719
|
-
while (k
|
|
2016
|
+
while (!text.atEnd(k) && text.charCodeAt(k) === 92)
|
|
1720
2017
|
k += 1;
|
|
1721
2018
|
if (k === i)
|
|
1722
2019
|
return 0;
|
|
@@ -1725,7 +2022,7 @@ function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
|
1725
2022
|
};
|
|
1726
2023
|
const atLineEnd = (i) => {
|
|
1727
2024
|
const b = skipHs(i);
|
|
1728
|
-
if (b
|
|
2025
|
+
if (text.atEnd(b) || openAt(b))
|
|
1729
2026
|
return true;
|
|
1730
2027
|
if (tokenEnd(scan, b) >= 0 || lineEndHidden(b))
|
|
1731
2028
|
return false;
|
|
@@ -1741,13 +2038,13 @@ function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
|
1741
2038
|
if (mk === 43 || mk === 45)
|
|
1742
2039
|
q = skipHs(q + 1);
|
|
1743
2040
|
let r = q;
|
|
1744
|
-
while (r
|
|
2041
|
+
while (!text.atEnd(r) && b64At(r))
|
|
1745
2042
|
r += 1;
|
|
1746
2043
|
if (r - q < 4) {
|
|
1747
|
-
if (isHead && r
|
|
2044
|
+
if (isHead && text.atEnd(r))
|
|
1748
2045
|
return LINE_OPEN;
|
|
1749
2046
|
r = q0;
|
|
1750
|
-
while (r
|
|
2047
|
+
while (!text.atEnd(r) && b64At(r))
|
|
1751
2048
|
r += 1;
|
|
1752
2049
|
if (r - q0 < 4)
|
|
1753
2050
|
return LINE_NONE;
|
|
@@ -1759,11 +2056,12 @@ function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
|
1759
2056
|
const at = text.indexOf(KEY, search);
|
|
1760
2057
|
if (at === -1)
|
|
1761
2058
|
break;
|
|
2059
|
+
text.attempt(at);
|
|
1762
2060
|
let p = at + KEY.length;
|
|
1763
2061
|
const d0 = p;
|
|
1764
|
-
while (p
|
|
2062
|
+
while (!text.atEnd(p) && tokenEnd(scan, p) < 0 && text.charCodeAt(p) >= 48 && text.charCodeAt(p) <= 57)
|
|
1765
2063
|
p += 1;
|
|
1766
|
-
if (p === d0 && p
|
|
2064
|
+
if (p === d0 && !text.atEnd(p)) {
|
|
1767
2065
|
search = at + KEY.length;
|
|
1768
2066
|
continue;
|
|
1769
2067
|
}
|
|
@@ -1778,7 +2076,7 @@ function collectHeadlessPpkSpans(scan, text, span, isHead) {
|
|
|
1778
2076
|
const r = bodyLineAt(from);
|
|
1779
2077
|
if (r === LINE_NONE)
|
|
1780
2078
|
break;
|
|
1781
|
-
end = r === LINE_OPEN ?
|
|
2079
|
+
end = r === LINE_OPEN ? text.readEnd() : r;
|
|
1782
2080
|
if (r === LINE_OPEN) {
|
|
1783
2081
|
open = true;
|
|
1784
2082
|
break;
|
|
@@ -1800,7 +2098,7 @@ const FRAGMENT_SECRET_PATTERNS = [
|
|
|
1800
2098
|
[valueArm("xox[baprs]-", "[A-Za-z0-9-]", 4, "needs-left-boundary"), "«redacted:slack-token:partial»"],
|
|
1801
2099
|
[valueArm("AKIA", "[0-9A-Z]", 6, "needs-left-boundary"), "«redacted:aws-key:partial»"],
|
|
1802
2100
|
[valueArm("ASIA", "[0-9A-Z]", 8, "needs-left-boundary"), "«redacted:aws-key:partial»"],
|
|
1803
|
-
[valueArm("(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-|(?:sk|rk)_(?:live|test|org)_|pypi
|
|
2101
|
+
[valueArm("(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-|(?:sk|rk)_(?:live|test|org)_|pypi-|npm_|hf_|ya29\\.)", "[A-Za-z0-9_-]", 8, "needs-left-boundary"), "«redacted:key:partial»"],
|
|
1804
2102
|
[valueArm("xapp-\\d-", "[A-Za-z0-9-]", 4, "needs-left-boundary"), "«redacted:slack-token:partial»"],
|
|
1805
2103
|
];
|
|
1806
2104
|
const DISPLAY_SAFE_URL_TOKEN = "«redacted:url»";
|
|
@@ -1882,46 +2180,26 @@ const isRegexSpace = (c) => c === 32 || (c >= 9 && c <= 13) || c === 0xa0 || c =
|
|
|
1882
2180
|
const isLineTerminator = (c) => c === 10 || c === 13 || c === 0x2028 || c === 0x2029;
|
|
1883
2181
|
const isControlCode = (c) => c < 0x20 || c === 0x7f;
|
|
1884
2182
|
const TOKEN_UNIT_Y = new RegExp(REDACTION_TOKEN_RE_SRC, "y");
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
let
|
|
1888
|
-
for (let i = 0; i < name.length; i++) {
|
|
1889
|
-
const c = name.charCodeAt(i);
|
|
1890
|
-
if (c !== 37) {
|
|
1891
|
-
out += name[i];
|
|
1892
|
-
continue;
|
|
1893
|
-
}
|
|
1894
|
-
const hex = name.slice(i + 1, i + 3);
|
|
1895
|
-
if (hex.length !== 2 || !/^[0-9A-Fa-f]{2}$/.test(hex))
|
|
1896
|
-
return undefined;
|
|
1897
|
-
const b = Number.parseInt(hex, 16);
|
|
1898
|
-
if (b >= 0x80)
|
|
1899
|
-
return undefined;
|
|
1900
|
-
out += String.fromCharCode(b);
|
|
1901
|
-
i += 2;
|
|
1902
|
-
}
|
|
1903
|
-
return out;
|
|
1904
|
-
}
|
|
1905
|
-
function credentialParamValueStart(text, p) {
|
|
1906
|
-
const limit = Math.min(text.length, p + CREDENTIAL_NAME_SCAN_MAX);
|
|
1907
|
-
let hasPct = false;
|
|
1908
|
-
for (let i = p; i < limit; i++) {
|
|
2183
|
+
function credentialParamValueStart(text, p, json) {
|
|
2184
|
+
let encoded = false;
|
|
2185
|
+
for (let i = p; !text.atEnd(i); i++) {
|
|
1909
2186
|
const c = text.charCodeAt(i);
|
|
1910
|
-
if (c === 37) {
|
|
1911
|
-
hasPct = true;
|
|
1912
|
-
continue;
|
|
1913
|
-
}
|
|
1914
2187
|
if (c === CH_EQ) {
|
|
1915
2188
|
if (i === p)
|
|
1916
2189
|
return -1;
|
|
1917
|
-
const
|
|
1918
|
-
return
|
|
2190
|
+
const raw = text.slice(p, i);
|
|
2191
|
+
return credentialNameAnchor(encoded ? receiverParamName(raw) : raw) !== undefined ? i + 1 : -1;
|
|
1919
2192
|
}
|
|
1920
|
-
if (
|
|
2193
|
+
if (c === 63 || c === 38 || c === 35 || isRegexSpace(c) || isControlCode(c) || (json && c === 34))
|
|
1921
2194
|
return -1;
|
|
2195
|
+
if (c === 37 || c === 43)
|
|
2196
|
+
encoded = true;
|
|
1922
2197
|
}
|
|
1923
2198
|
return -1;
|
|
1924
2199
|
}
|
|
2200
|
+
function receiverParamName(raw) {
|
|
2201
|
+
return new URLSearchParams(`${raw}=`).keys().next().value ?? raw;
|
|
2202
|
+
}
|
|
1925
2203
|
function tokenUnitEnd(text, p) {
|
|
1926
2204
|
TOKEN_UNIT_Y.lastIndex = p;
|
|
1927
2205
|
return TOKEN_UNIT_Y.test(text) ? TOKEN_UNIT_Y.lastIndex : -1;
|
|
@@ -2388,7 +2666,8 @@ function reachAt(ix, d, self) {
|
|
|
2388
2666
|
return ix.dEnd2[d] < 0 ? -1 : ix.reach2[d];
|
|
2389
2667
|
}
|
|
2390
2668
|
const FOOT_NONE = 0x7fffffff;
|
|
2391
|
-
|
|
2669
|
+
const NO_DELIM_POSITIONS = new Int32Array(0);
|
|
2670
|
+
function buildForensicScan(tokens, rows, armCount, positionsOf) {
|
|
2392
2671
|
return {
|
|
2393
2672
|
rows,
|
|
2394
2673
|
tokens,
|
|
@@ -2399,6 +2678,7 @@ function buildForensicScan(tokens, rows, armCount) {
|
|
|
2399
2678
|
footLo: FOOT_NONE,
|
|
2400
2679
|
footHi: -1,
|
|
2401
2680
|
armFoot: new Int32Array(2 * armCount),
|
|
2681
|
+
execs: [],
|
|
2402
2682
|
lastAt: -1,
|
|
2403
2683
|
headsRead: { a: NO_URL_SEGMENTS, n: 0 },
|
|
2404
2684
|
headsWrite: { a: NO_URL_SEGMENTS, n: 0 },
|
|
@@ -2408,6 +2688,7 @@ function buildForensicScan(tokens, rows, armCount) {
|
|
|
2408
2688
|
opsWrite: { a: NO_URL_SEGMENTS, n: 0, cut: OPS_UNCUT },
|
|
2409
2689
|
hdr: { search: 0, contentEnd: 0, next: 0, hitLimit: false, jsonEnd: false },
|
|
2410
2690
|
delimPos: new Map(),
|
|
2691
|
+
positionsOf,
|
|
2411
2692
|
delimIx: new Map(),
|
|
2412
2693
|
delimIxRows: rows,
|
|
2413
2694
|
};
|
|
@@ -2418,6 +2699,11 @@ function noteEvidenceRead(scan, p) {
|
|
|
2418
2699
|
if (p > scan.footHi)
|
|
2419
2700
|
scan.footHi = p;
|
|
2420
2701
|
}
|
|
2702
|
+
function noteExecution(scan, lo, hi, from) {
|
|
2703
|
+
if (lo > hi)
|
|
2704
|
+
return;
|
|
2705
|
+
scan.execs.push(lo, hi, from);
|
|
2706
|
+
}
|
|
2421
2707
|
function footprintClean(dirty, lo, hi) {
|
|
2422
2708
|
if (lo > hi)
|
|
2423
2709
|
return true;
|
|
@@ -2674,16 +2960,21 @@ export function unitCountsWithinForTest(table, queries) {
|
|
|
2674
2960
|
anchor: Int32Array.from(sorted, keyOf),
|
|
2675
2961
|
closeAt: new Int32Array(sorted.length).fill(NOT_CLOSED),
|
|
2676
2962
|
};
|
|
2677
|
-
const scan = buildForensicScan(NO_TOKEN_UNITS, rows, 1);
|
|
2963
|
+
const scan = buildForensicScan(NO_TOKEN_UNITS, rows, 1, () => NO_DELIM_POSITIONS);
|
|
2678
2964
|
return queries.map(([from, to, max, self]) => {
|
|
2679
2965
|
scan.self = self === undefined ? NO_SELF : readingKey(familyCode("prose"), self);
|
|
2680
2966
|
return measureWithin(scan, from, to, max);
|
|
2681
2967
|
});
|
|
2682
2968
|
}
|
|
2683
|
-
function delimPositions(scan,
|
|
2969
|
+
function delimPositions(scan, kind) {
|
|
2684
2970
|
const hit = scan.delimPos.get(kind);
|
|
2685
2971
|
if (hit !== undefined)
|
|
2686
2972
|
return hit;
|
|
2973
|
+
const pos = scan.positionsOf(kind);
|
|
2974
|
+
scan.delimPos.set(kind, pos);
|
|
2975
|
+
return pos;
|
|
2976
|
+
}
|
|
2977
|
+
function delimPositionsOf(text, kind) {
|
|
2687
2978
|
const out = [];
|
|
2688
2979
|
switch (kind) {
|
|
2689
2980
|
case "ssh2-open":
|
|
@@ -2694,11 +2985,13 @@ function delimPositions(scan, text, kind) {
|
|
|
2694
2985
|
ssh2ScanBytes += text.length;
|
|
2695
2986
|
break;
|
|
2696
2987
|
}
|
|
2697
|
-
case "pem-end":
|
|
2988
|
+
case "pem-end": {
|
|
2989
|
+
const lines = new ScanReader(text);
|
|
2698
2990
|
for (let b = text.indexOf(PEM_END_OPEN); b >= 0; b = text.indexOf(PEM_END_OPEN, b + 1))
|
|
2699
|
-
if (pemFenceLineEnd(
|
|
2991
|
+
if (pemFenceLineEnd(lines, b + PEM_END_OPEN.length) >= 0)
|
|
2700
2992
|
out.push(b);
|
|
2701
2993
|
break;
|
|
2994
|
+
}
|
|
2702
2995
|
case "at":
|
|
2703
2996
|
case "at-json":
|
|
2704
2997
|
for (let p = text.indexOf("@"); p >= 0; p = text.indexOf("@", p + 1)) {
|
|
@@ -2713,11 +3006,9 @@ function delimPositions(scan, text, kind) {
|
|
|
2713
3006
|
}
|
|
2714
3007
|
break;
|
|
2715
3008
|
}
|
|
2716
|
-
|
|
2717
|
-
scan.delimPos.set(kind, pos);
|
|
2718
|
-
return pos;
|
|
3009
|
+
return Int32Array.from(out);
|
|
2719
3010
|
}
|
|
2720
|
-
function delimIndexOf(scan,
|
|
3011
|
+
function delimIndexOf(scan, kind) {
|
|
2721
3012
|
const t = scan.rows;
|
|
2722
3013
|
if (scan.delimIxRows !== t) {
|
|
2723
3014
|
scan.delimIx = new Map();
|
|
@@ -2727,7 +3018,7 @@ function delimIndexOf(scan, text, kind) {
|
|
|
2727
3018
|
const hit = byKind.get(kind);
|
|
2728
3019
|
if (hit !== undefined)
|
|
2729
3020
|
return hit;
|
|
2730
|
-
const pos = delimPositions(scan,
|
|
3021
|
+
const pos = delimPositions(scan, kind);
|
|
2731
3022
|
const n = pos.length;
|
|
2732
3023
|
const nextNotHidden = new Int32Array(n + 1);
|
|
2733
3024
|
const nextFree = new Int32Array(n + 1);
|
|
@@ -2787,9 +3078,9 @@ function bucketFirstFrom(b, i, n) {
|
|
|
2787
3078
|
const k = lowerBound(b, i);
|
|
2788
3079
|
return k < b.length ? b[k] : n;
|
|
2789
3080
|
}
|
|
2790
|
-
function firstDelim(scan,
|
|
3081
|
+
function firstDelim(scan, kind, from, wantFree) {
|
|
2791
3082
|
noteEvidenceRead(scan, from);
|
|
2792
|
-
const di = delimIndexOf(scan,
|
|
3083
|
+
const di = delimIndexOf(scan, kind);
|
|
2793
3084
|
const n = di.pos.length;
|
|
2794
3085
|
const bucket = (wantFree ? di.onlyCoveredBy : di.onlyHiddenBy).get(scan.self);
|
|
2795
3086
|
const firstAt = (i) => (i >= n ? n : Math.min(wantFree ? di.nextFree[i] : di.nextNotHidden[i], bucketFirstFrom(bucket, i, n)));
|
|
@@ -2803,11 +3094,11 @@ function firstDelim(scan, text, kind, from, wantFree) {
|
|
|
2803
3094
|
j = firstAt(lowerBound(di.pos, own.maxClose[k]));
|
|
2804
3095
|
}
|
|
2805
3096
|
const at = j >= n ? -1 : di.pos[j];
|
|
2806
|
-
noteEvidenceRead(scan, at < 0 ?
|
|
3097
|
+
noteEvidenceRead(scan, at < 0 ? VIEW_END : at);
|
|
2807
3098
|
return at;
|
|
2808
3099
|
}
|
|
2809
|
-
function lastNotHiddenDelim(scan,
|
|
2810
|
-
const di = delimIndexOf(scan,
|
|
3100
|
+
function lastNotHiddenDelim(scan, kind, a, b) {
|
|
3101
|
+
const di = delimIndexOf(scan, kind);
|
|
2811
3102
|
const bucket = di.onlyHiddenBy.get(scan.self);
|
|
2812
3103
|
const lastAt = (j) => {
|
|
2813
3104
|
let best = di.prevNotHidden[j];
|
|
@@ -2834,13 +3125,12 @@ function lastNotHiddenDelim(scan, text, kind, a, b) {
|
|
|
2834
3125
|
return best >= 0 && di.pos[best] >= a ? di.pos[best] : -1;
|
|
2835
3126
|
}
|
|
2836
3127
|
function scanUrlRun(scan, text, i, kind, json) {
|
|
2837
|
-
const n = text.length;
|
|
2838
3128
|
noteEvidenceRead(scan, i);
|
|
2839
3129
|
scan.lastAt = -1;
|
|
2840
|
-
run: while (i
|
|
3130
|
+
run: while (!text.atEnd(i)) {
|
|
2841
3131
|
const unit = crossEndAt(scan, i);
|
|
2842
3132
|
if (unit >= 0) {
|
|
2843
|
-
const at = lastNotHiddenDelim(scan,
|
|
3133
|
+
const at = lastNotHiddenDelim(scan, json ? "at-json" : "at", i, unit);
|
|
2844
3134
|
if (at > scan.lastAt)
|
|
2845
3135
|
scan.lastAt = at;
|
|
2846
3136
|
i = unit;
|
|
@@ -2848,7 +3138,7 @@ function scanUrlRun(scan, text, i, kind, json) {
|
|
|
2848
3138
|
}
|
|
2849
3139
|
const c = text.charCodeAt(i);
|
|
2850
3140
|
if (json && c === 92) {
|
|
2851
|
-
if (i + 1
|
|
3141
|
+
if (!text.atEnd(i + 1) && !isLineTerminator(text.charCodeAt(i + 1))) {
|
|
2852
3142
|
i += 2;
|
|
2853
3143
|
continue;
|
|
2854
3144
|
}
|
|
@@ -2885,7 +3175,7 @@ function matchUserinfoAt(scan, text, p, json, isHead) {
|
|
|
2885
3175
|
const probeEnd = scanUrlRun(scan, text, p, "plain-user", json);
|
|
2886
3176
|
const keyId = probeEnd > p && text.charCodeAt(probeEnd) === 58 && readableCover(scan, p, probeEnd);
|
|
2887
3177
|
const runEnd = scanUrlRun(scan, text, p, keyId ? "token-pass" : "plain-pass", json);
|
|
2888
|
-
if (isHead && runEnd
|
|
3178
|
+
if (isHead && runEnd > p && text.atEnd(runEnd))
|
|
2889
3179
|
return runEnd;
|
|
2890
3180
|
const at = scan.lastAt;
|
|
2891
3181
|
if (at <= p)
|
|
@@ -2893,6 +3183,7 @@ function matchUserinfoAt(scan, text, p, json, isHead) {
|
|
|
2893
3183
|
return at;
|
|
2894
3184
|
}
|
|
2895
3185
|
const URL_SEG_STRIDE = 4;
|
|
3186
|
+
const URL_PARAM_DELIMS = /[?&#]/g;
|
|
2896
3187
|
const URL_SEG_MAX_INTS = 3 * 1_048_576;
|
|
2897
3188
|
const NO_URL_SEGMENTS = new Int32Array(0);
|
|
2898
3189
|
const ANCHOR_SEG_STRIDE = 4;
|
|
@@ -2922,12 +3213,12 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
2922
3213
|
const phn = dirty === undefined ? 0 : hr.n;
|
|
2923
3214
|
let pc = 0;
|
|
2924
3215
|
for (let from = 0;;) {
|
|
2925
|
-
|
|
2926
|
-
const m = head.exec(text);
|
|
3216
|
+
const m = text.search(head, from);
|
|
2927
3217
|
if (m === null)
|
|
2928
3218
|
break;
|
|
2929
3219
|
const colon = m.index;
|
|
2930
3220
|
const start = colon + 3;
|
|
3221
|
+
text.attempt(start);
|
|
2931
3222
|
while (pc < phn && ph[pc] < colon)
|
|
2932
3223
|
pc += URL_SEG_STRIDE;
|
|
2933
3224
|
const known = pc < phn && ph[pc] === colon;
|
|
@@ -2948,8 +3239,9 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
2948
3239
|
lo = scan.footLo;
|
|
2949
3240
|
hi = scan.footHi;
|
|
2950
3241
|
urlSegmentRuns += 1;
|
|
3242
|
+
noteExecution(scan, lo, hi, start);
|
|
2951
3243
|
if (at >= 0 && at !== (known ? ph[pc + 1] : -2)) {
|
|
2952
|
-
const undecided = isHead &&
|
|
3244
|
+
const undecided = isHead && text.atEnd(at);
|
|
2953
3245
|
span(start, at, colon, undecided ? NOT_CLOSED : at, undecided);
|
|
2954
3246
|
}
|
|
2955
3247
|
}
|
|
@@ -2971,13 +3263,15 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
2971
3263
|
const pp = pr.a;
|
|
2972
3264
|
const ppn = dirty === undefined ? 0 : pr.n;
|
|
2973
3265
|
let qc = 0;
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3266
|
+
let resume = 0;
|
|
3267
|
+
for (let m = text.search(URL_PARAM_DELIMS, 0); m !== null; m = text.search(URL_PARAM_DELIMS, resume)) {
|
|
3268
|
+
const i = m.index;
|
|
3269
|
+
resume = i + 1;
|
|
3270
|
+
text.attempt(i + 1);
|
|
3271
|
+
const valueStart = credentialParamValueStart(text, i + 1, json);
|
|
2979
3272
|
if (valueStart < 0)
|
|
2980
3273
|
continue;
|
|
3274
|
+
text.attempt(valueStart);
|
|
2981
3275
|
while (qc < ppn && pp[qc] < i)
|
|
2982
3276
|
qc += URL_SEG_STRIDE;
|
|
2983
3277
|
const known = qc < ppn && pp[qc] === i;
|
|
@@ -2998,6 +3292,7 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
2998
3292
|
lo = scan.footLo;
|
|
2999
3293
|
hi = scan.footHi;
|
|
3000
3294
|
urlSegmentRuns += 1;
|
|
3295
|
+
noteExecution(scan, lo, hi, valueStart);
|
|
3001
3296
|
if (valueEnd > valueStart && valueEnd !== (known ? pp[qc + 1] : -2))
|
|
3002
3297
|
span(valueStart, valueEnd, i, NOT_CLOSED);
|
|
3003
3298
|
}
|
|
@@ -3014,7 +3309,7 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
3014
3309
|
armLo = lo;
|
|
3015
3310
|
if (hi > armHi)
|
|
3016
3311
|
armHi = hi;
|
|
3017
|
-
|
|
3312
|
+
resume = valueEnd;
|
|
3018
3313
|
}
|
|
3019
3314
|
scan.headsRead = hw;
|
|
3020
3315
|
scan.headsWrite = hr;
|
|
@@ -3024,28 +3319,25 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
|
|
|
3024
3319
|
scan.footHi = armHi;
|
|
3025
3320
|
}
|
|
3026
3321
|
const JSON_FIELD_ANCHOR = '"';
|
|
3027
|
-
const
|
|
3322
|
+
const JSON_FIELD_HEAD_MAX = Math.max(...JSON_FIELD_QUOTE_FORMS.map((f) => f.length));
|
|
3028
3323
|
function jsonSecretFieldValueQuoteAt(text, p, depth) {
|
|
3029
3324
|
const form = JSON_FIELD_QUOTE_FORMS[depth];
|
|
3030
|
-
const n = text.length;
|
|
3031
3325
|
const nameFrom = p + form.length;
|
|
3032
3326
|
let i = nameFrom;
|
|
3033
|
-
for (; i
|
|
3327
|
+
for (; !text.atEnd(i); i++) {
|
|
3034
3328
|
const c = text.charCodeAt(i);
|
|
3035
|
-
if (!(
|
|
3329
|
+
if (!isJsonFieldNameCode(c))
|
|
3036
3330
|
break;
|
|
3037
|
-
if (i - nameFrom >= CREDENTIAL_NAME_MAX)
|
|
3038
|
-
return -1;
|
|
3039
3331
|
}
|
|
3040
3332
|
if (i === nameFrom || !text.startsWith(form, i) || credentialNameAnchor(text.slice(nameFrom, i)) === undefined)
|
|
3041
3333
|
return -1;
|
|
3042
3334
|
i += form.length;
|
|
3043
|
-
while (i
|
|
3335
|
+
while (!text.atEnd(i) && isRegexSpace(text.charCodeAt(i)))
|
|
3044
3336
|
i += 1;
|
|
3045
3337
|
if (text.charCodeAt(i) !== CH_COLON)
|
|
3046
3338
|
return -1;
|
|
3047
3339
|
i += 1;
|
|
3048
|
-
while (i
|
|
3340
|
+
while (!text.atEnd(i) && isRegexSpace(text.charCodeAt(i)))
|
|
3049
3341
|
i += 1;
|
|
3050
3342
|
return text.startsWith(form, i) ? i : -1;
|
|
3051
3343
|
}
|
|
@@ -3060,7 +3352,7 @@ const packUnit8 = (kind, next) => next * 8 + kind;
|
|
|
3060
3352
|
const unit8Kind = (u) => (u % 8);
|
|
3061
3353
|
const unit8Next = (u) => (u - (u % 8)) / 8;
|
|
3062
3354
|
function escapedUnitAt(text, i, depth) {
|
|
3063
|
-
if (
|
|
3355
|
+
if (text.atEnd(i))
|
|
3064
3356
|
return packUnit8(U_END, i);
|
|
3065
3357
|
if (depth === 0) {
|
|
3066
3358
|
const c = text.charCodeAt(i);
|
|
@@ -3119,7 +3411,7 @@ function collectJsonSecretFieldSpans(text, span, isHead) {
|
|
|
3119
3411
|
let from = 0;
|
|
3120
3412
|
for (let p = text.indexOf(JSON_FIELD_ANCHOR); p >= 0;) {
|
|
3121
3413
|
let run = 0;
|
|
3122
|
-
while (run <
|
|
3414
|
+
while (run < JSON_FIELD_HEAD_MAX - 1 && p - run - 1 >= from && text.charCodeAt(p - run - 1) === CH_BACKSLASH)
|
|
3123
3415
|
run += 1;
|
|
3124
3416
|
let next = -1;
|
|
3125
3417
|
for (let d = JSON_FIELD_QUOTE_FORMS.length - 1; d >= 0 && next < 0; d--) {
|
|
@@ -3127,14 +3419,15 @@ function collectJsonSecretFieldSpans(text, span, isHead) {
|
|
|
3127
3419
|
const start = p - (form.length - 1);
|
|
3128
3420
|
if (start < p - run)
|
|
3129
3421
|
continue;
|
|
3422
|
+
text.attempt(start);
|
|
3130
3423
|
const q = jsonSecretFieldValueQuoteAt(text, start, d);
|
|
3131
3424
|
const found = q < 0 ? -1 : jsonStringEndAt(text, q + form.length, d, isHead);
|
|
3132
3425
|
if (found === -1)
|
|
3133
3426
|
continue;
|
|
3134
3427
|
const open = found === STRING_OPEN;
|
|
3135
|
-
const end = open ? text.
|
|
3428
|
+
const end = open ? text.readEnd() : found;
|
|
3136
3429
|
span(q, end, q, open ? NOT_CLOSED : end - form.length, open, JSON_FIELD_VALUE_REPLS[d]);
|
|
3137
|
-
from = scanResumeAfterHit(start, end,
|
|
3430
|
+
from = scanResumeAfterHit(start, end, end - q);
|
|
3138
3431
|
next = text.indexOf(JSON_FIELD_ANCHOR, from);
|
|
3139
3432
|
if (next < 0)
|
|
3140
3433
|
return;
|
|
@@ -3187,7 +3480,7 @@ function readTextUnit(text, i, json) {
|
|
|
3187
3480
|
return packUnit(c, 1);
|
|
3188
3481
|
if (c === CH_QUOTE)
|
|
3189
3482
|
return packUnit(JSON_STRING_END, 1);
|
|
3190
|
-
if (c !== CH_BACKSLASH || i + 1
|
|
3483
|
+
if (c !== CH_BACKSLASH || text.atEnd(i + 1))
|
|
3191
3484
|
return packUnit(c, 1);
|
|
3192
3485
|
switch (text.charCodeAt(i + 1)) {
|
|
3193
3486
|
case CH_n: return packUnit(CH_LF, 2);
|
|
@@ -3245,16 +3538,13 @@ function anchorHeadAt(scan, text, op, json) {
|
|
|
3245
3538
|
i -= quoteLen;
|
|
3246
3539
|
}
|
|
3247
3540
|
const nameEnd = i + 1;
|
|
3248
|
-
const floor = Math.max(-1, i - (CREDENTIAL_NAME_MAX + 2));
|
|
3249
3541
|
let j = i;
|
|
3250
|
-
while (j
|
|
3542
|
+
while (j >= 0 && isIdentCode(text.charCodeAt(j)))
|
|
3251
3543
|
j -= 1;
|
|
3252
3544
|
anchoredScanUnits += nameEnd - (j + 1);
|
|
3253
3545
|
const bound = j + 1 < nameEnd ? nameBoundAt(scan, Math.max(j, 0), nameEnd) : -1;
|
|
3254
3546
|
if (bound > j)
|
|
3255
3547
|
j = bound - 1;
|
|
3256
|
-
else if (j === floor && j >= 0 && isIdentCode(text.charCodeAt(j)))
|
|
3257
|
-
return undefined;
|
|
3258
3548
|
let nameStart = j + 1;
|
|
3259
3549
|
let afterEscape = false;
|
|
3260
3550
|
if (j >= 0 && text.charCodeAt(j) === CH_BACKSLASH && escapedAt(text, j + 1)) {
|
|
@@ -3300,9 +3590,8 @@ function anchorHeadAt(scan, text, op, json) {
|
|
|
3300
3590
|
return { strength, quotedName: quote !== 0, spacedLeft, listSep, runStart };
|
|
3301
3591
|
}
|
|
3302
3592
|
function quotedValueEnd(text, cs, quote, json, isHead) {
|
|
3303
|
-
const n = text.length;
|
|
3304
3593
|
let i = cs;
|
|
3305
|
-
while (i
|
|
3594
|
+
while (!text.atEnd(i)) {
|
|
3306
3595
|
const unit = readAnchorUnit(text, i, json);
|
|
3307
3596
|
const ch = unitChOf(unit);
|
|
3308
3597
|
if (ch === quote)
|
|
@@ -3311,7 +3600,7 @@ function quotedValueEnd(text, cs, quote, json, isHead) {
|
|
|
3311
3600
|
return -1;
|
|
3312
3601
|
i += unitLenOf(unit);
|
|
3313
3602
|
if (ch === CH_BACKSLASH && quote !== JSON_STRING_END) {
|
|
3314
|
-
if (i
|
|
3603
|
+
if (text.atEnd(i))
|
|
3315
3604
|
break;
|
|
3316
3605
|
const escaped = readAnchorUnit(text, i, json);
|
|
3317
3606
|
if (unitChOf(escaped) === JSON_STRING_END)
|
|
@@ -3326,6 +3615,7 @@ function buildBareValueMemo() {
|
|
|
3326
3615
|
return {
|
|
3327
3616
|
from: new Int32Array(4),
|
|
3328
3617
|
at: new Int32Array(4).fill(-1),
|
|
3618
|
+
end: new Uint8Array(4),
|
|
3329
3619
|
netFrom: new Int32Array(4).fill(NO_MEMO_GROUP),
|
|
3330
3620
|
net: new Int32Array(16),
|
|
3331
3621
|
runFrom: new Int32Array(4).fill(NO_MEMO_GROUP),
|
|
@@ -3334,14 +3624,17 @@ function buildBareValueMemo() {
|
|
|
3334
3624
|
}
|
|
3335
3625
|
const listSepSlot = (listSep) => (listSep === 0 ? 0 : listSep === CH_AMP ? 1 : listSep === CH_SEMI ? 2 : 3);
|
|
3336
3626
|
function bareValueEnd(text, s, json, listSep, memo) {
|
|
3337
|
-
const n = text.length;
|
|
3338
3627
|
const k = listSepSlot(listSep);
|
|
3339
3628
|
let i;
|
|
3340
|
-
if (memo.from[k] <= s && s <= memo.at[k])
|
|
3629
|
+
if (memo.from[k] <= s && s <= memo.at[k]) {
|
|
3341
3630
|
i = memo.at[k];
|
|
3631
|
+
if (memo.end[k] === 1)
|
|
3632
|
+
text.readEnd();
|
|
3633
|
+
}
|
|
3342
3634
|
else {
|
|
3343
3635
|
i = s;
|
|
3344
|
-
|
|
3636
|
+
let reachedEnd = false;
|
|
3637
|
+
while (!(reachedEnd = text.atEnd(i))) {
|
|
3345
3638
|
const unit = readAnchorUnit(text, i, json);
|
|
3346
3639
|
const ch = unitChOf(unit);
|
|
3347
3640
|
if (ch === JSON_STRING_END || isRegexSpace(ch))
|
|
@@ -3350,7 +3643,7 @@ function bareValueEnd(text, s, json, listSep, memo) {
|
|
|
3350
3643
|
break;
|
|
3351
3644
|
const next = i + unitLenOf(unit);
|
|
3352
3645
|
if (isQuoteUnit(ch)) {
|
|
3353
|
-
if (
|
|
3646
|
+
if ((reachedEnd = text.atEnd(next)))
|
|
3354
3647
|
break;
|
|
3355
3648
|
if (endsValueUnit(unitChOf(readAnchorUnit(text, next, json))))
|
|
3356
3649
|
break;
|
|
@@ -3359,6 +3652,7 @@ function bareValueEnd(text, s, json, listSep, memo) {
|
|
|
3359
3652
|
}
|
|
3360
3653
|
memo.from[k] = s;
|
|
3361
3654
|
memo.at[k] = i;
|
|
3655
|
+
memo.end[k] = reachedEnd ? 1 : 0;
|
|
3362
3656
|
memo.netFrom[k] = NO_MEMO_GROUP;
|
|
3363
3657
|
memo.runFrom[k] = NO_MEMO_GROUP;
|
|
3364
3658
|
}
|
|
@@ -3411,21 +3705,20 @@ function bareValueEnd(text, s, json, listSep, memo) {
|
|
|
3411
3705
|
return e;
|
|
3412
3706
|
}
|
|
3413
3707
|
function literalValueAt(text, s, json, bare, listSep, isHead, memo) {
|
|
3414
|
-
|
|
3415
|
-
if (s >= n)
|
|
3708
|
+
if (text.atEnd(s))
|
|
3416
3709
|
return undefined;
|
|
3417
3710
|
const firstUnit = readAnchorUnit(text, s, json);
|
|
3418
3711
|
const first = unitChOf(firstUnit);
|
|
3419
3712
|
let vs = s;
|
|
3420
3713
|
if (isQuoteUnit(first) || first === JSON_STRING_END) {
|
|
3421
3714
|
vs = s + unitLenOf(firstUnit);
|
|
3422
|
-
if (vs
|
|
3715
|
+
if (text.atEnd(vs))
|
|
3423
3716
|
return undefined;
|
|
3424
3717
|
if (!isAsciiAlnumCode(unitChOf(readAnchorUnit(text, vs, json))))
|
|
3425
3718
|
return undefined;
|
|
3426
3719
|
const close = quotedValueEnd(text, vs, first, json, isHead);
|
|
3427
3720
|
if (close === STRING_OPEN)
|
|
3428
|
-
return { start: vs, end:
|
|
3721
|
+
return { start: vs, end: text.readEnd(), quoted: true, open: true };
|
|
3429
3722
|
if (close >= 0)
|
|
3430
3723
|
return { start: vs, end: close, quoted: true };
|
|
3431
3724
|
}
|
|
@@ -3448,11 +3741,11 @@ function literalValueAt(text, s, json, bare, listSep, isHead, memo) {
|
|
|
3448
3741
|
}
|
|
3449
3742
|
if (isProgramIdentStartCode(text.charCodeAt(vs))) {
|
|
3450
3743
|
let k = vs;
|
|
3451
|
-
while (k
|
|
3744
|
+
while (!text.atEnd(k) && isProgramIdentCode(text.charCodeAt(k)))
|
|
3452
3745
|
k += 1;
|
|
3453
3746
|
anchoredScanUnits += k - vs;
|
|
3454
3747
|
const after = text.charCodeAt(k);
|
|
3455
|
-
if (after === CH_LPAREN || after === CH_LBRACKET || (after === CH_DOT && k + 1
|
|
3748
|
+
if (after === CH_LPAREN || after === CH_LBRACKET || (after === CH_DOT && !text.atEnd(k + 1) && isProgramIdentStartCode(text.charCodeAt(k + 1))))
|
|
3456
3749
|
return undefined;
|
|
3457
3750
|
}
|
|
3458
3751
|
const e = bareValueEnd(text, vs, json, listSep, memo);
|
|
@@ -3471,7 +3764,7 @@ function literalValueAt(text, s, json, bare, listSep, isHead, memo) {
|
|
|
3471
3764
|
case "goes-on":
|
|
3472
3765
|
return undefined;
|
|
3473
3766
|
case "undecided":
|
|
3474
|
-
return { start: vs, end: text.
|
|
3767
|
+
return { start: vs, end: text.readEnd(), quoted: false, open: true };
|
|
3475
3768
|
default: {
|
|
3476
3769
|
const unhandled = rest;
|
|
3477
3770
|
throw new Error(`redact: unhandled line-key rest ${String(unhandled)}`);
|
|
@@ -3481,9 +3774,8 @@ function literalValueAt(text, s, json, bare, listSep, isHead, memo) {
|
|
|
3481
3774
|
return { start: vs, end: e, quoted: false };
|
|
3482
3775
|
}
|
|
3483
3776
|
function lineKeyRestAt(text, e, json, isHead) {
|
|
3484
|
-
const n = text.length;
|
|
3485
3777
|
let i = e;
|
|
3486
|
-
while (i
|
|
3778
|
+
while (!text.atEnd(i)) {
|
|
3487
3779
|
const unit = readAnchorUnit(text, i, json);
|
|
3488
3780
|
const ch = unitChOf(unit);
|
|
3489
3781
|
if (isInlineSpaceUnit(ch) || (ch >= 0 && INVISIBLE_UNIT_CLASS[ch] === 1)) {
|
|
@@ -3545,9 +3837,8 @@ function declarativeBareAt(text, head, spacedRight, json) {
|
|
|
3545
3837
|
return spacedRight && lineHeadBefore(text, head.runStart, json) ? "line-key" : "never";
|
|
3546
3838
|
}
|
|
3547
3839
|
function schemeValueAt(text, s, json) {
|
|
3548
|
-
const n = text.length;
|
|
3549
3840
|
let i = s;
|
|
3550
|
-
if (i
|
|
3841
|
+
if (text.atEnd(i))
|
|
3551
3842
|
return undefined;
|
|
3552
3843
|
const opening = readAnchorUnit(text, i, json);
|
|
3553
3844
|
if (isQuoteUnit(unitChOf(opening)) || unitChOf(opening) === JSON_STRING_END)
|
|
@@ -3559,14 +3850,14 @@ function schemeValueAt(text, s, json) {
|
|
|
3559
3850
|
anchoredScanUnits += REDACTION_MARK.length;
|
|
3560
3851
|
}
|
|
3561
3852
|
else {
|
|
3562
|
-
while (i
|
|
3853
|
+
while (!text.atEnd(i) && i - w <= STRONG_AUTH_SCHEME_MAX && (isIdentStartCode(text.charCodeAt(i))))
|
|
3563
3854
|
i += 1;
|
|
3564
3855
|
anchoredScanUnits += i - w;
|
|
3565
3856
|
if (i - w > STRONG_AUTH_SCHEME_MAX || !STRONG_AUTH_SCHEMES.has(text.slice(w, i).toLowerCase()))
|
|
3566
3857
|
return undefined;
|
|
3567
3858
|
}
|
|
3568
3859
|
let separated = false;
|
|
3569
|
-
while (i
|
|
3860
|
+
while (!text.atEnd(i)) {
|
|
3570
3861
|
const unit = readAnchorUnit(text, i, json);
|
|
3571
3862
|
const ch = unitChOf(unit);
|
|
3572
3863
|
if (!isInlineSpaceUnit(ch) && !isSchemeDelimiterCode(ch))
|
|
@@ -3579,30 +3870,30 @@ function schemeValueAt(text, s, json) {
|
|
|
3579
3870
|
const vs = i;
|
|
3580
3871
|
if (engineMarked) {
|
|
3581
3872
|
let k = i;
|
|
3582
|
-
while (k
|
|
3873
|
+
while (!text.atEnd(k) && isToken68Code(text.charCodeAt(k)))
|
|
3583
3874
|
k += 1;
|
|
3584
|
-
while (k
|
|
3875
|
+
while (!text.atEnd(k) && text.charCodeAt(k) === CH_EQ)
|
|
3585
3876
|
k += 1;
|
|
3586
3877
|
if (k - vs >= BEARER_VALUE_MIN) {
|
|
3587
3878
|
anchoredScanUnits += k - vs;
|
|
3588
3879
|
return { start: vs, end: k, quoted: false };
|
|
3589
3880
|
}
|
|
3590
3881
|
}
|
|
3591
|
-
if (i
|
|
3882
|
+
if (text.atEnd(i) || !isAsciiAlnumCode(text.charCodeAt(i)))
|
|
3592
3883
|
return undefined;
|
|
3593
|
-
while (i
|
|
3884
|
+
while (!text.atEnd(i) && isToken68Code(text.charCodeAt(i)))
|
|
3594
3885
|
i += 1;
|
|
3595
|
-
while (i
|
|
3886
|
+
while (!text.atEnd(i) && text.charCodeAt(i) === CH_EQ)
|
|
3596
3887
|
i += 1;
|
|
3597
3888
|
anchoredScanUnits += i - vs;
|
|
3598
3889
|
const e = i;
|
|
3599
|
-
while (i
|
|
3890
|
+
while (!text.atEnd(i)) {
|
|
3600
3891
|
const unit = readAnchorUnit(text, i, json);
|
|
3601
3892
|
if (!isInlineSpaceUnit(unitChOf(unit)))
|
|
3602
3893
|
break;
|
|
3603
3894
|
i += unitLenOf(unit);
|
|
3604
3895
|
}
|
|
3605
|
-
if (i
|
|
3896
|
+
if (!text.atEnd(i) && !endsHeaderValueUnit(unitChOf(readAnchorUnit(text, i, json))))
|
|
3606
3897
|
return undefined;
|
|
3607
3898
|
return { start: vs, end: e, quoted: false };
|
|
3608
3899
|
}
|
|
@@ -3610,10 +3901,9 @@ function anchoredValueAt(scan, text, op, json, span, isHead, memo) {
|
|
|
3610
3901
|
const head = anchorHeadAt(scan, text, op, json);
|
|
3611
3902
|
if (head === undefined)
|
|
3612
3903
|
return;
|
|
3613
|
-
const n = text.length;
|
|
3614
3904
|
let s = op + 1;
|
|
3615
3905
|
let spacedRight = false;
|
|
3616
|
-
while (s
|
|
3906
|
+
while (!text.atEnd(s)) {
|
|
3617
3907
|
const unit = readAnchorUnit(text, s, json);
|
|
3618
3908
|
if (!isInlineSpaceUnit(unitChOf(unit)))
|
|
3619
3909
|
break;
|
|
@@ -3680,6 +3970,7 @@ function collectAnchoredValueSpans(scan, text, json, span, isHead) {
|
|
|
3680
3970
|
if (!known && dirty !== undefined && op < rd.cut)
|
|
3681
3971
|
continue;
|
|
3682
3972
|
scan.self = readingKey(anchorFamily, op);
|
|
3973
|
+
text.attempt(op + 1);
|
|
3683
3974
|
let lo;
|
|
3684
3975
|
let hi;
|
|
3685
3976
|
let answer;
|
|
@@ -3695,6 +3986,7 @@ function collectAnchoredValueSpans(scan, text, json, span, isHead) {
|
|
|
3695
3986
|
hi = scan.footHi;
|
|
3696
3987
|
if (lo > hi)
|
|
3697
3988
|
continue;
|
|
3989
|
+
noteExecution(scan, lo, hi, op + 1);
|
|
3698
3990
|
answer = nameBoundAt(scan, lo, hi);
|
|
3699
3991
|
}
|
|
3700
3992
|
if (wr.cut === OPS_UNCUT) {
|
|
@@ -3749,10 +4041,9 @@ export function resetDiagnosticScanUnitsForTest() {
|
|
|
3749
4041
|
diagnosticScanUnits = 0;
|
|
3750
4042
|
}
|
|
3751
4043
|
function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
|
|
3752
|
-
const n = text.length;
|
|
3753
4044
|
const readRun = (from, isValue) => {
|
|
3754
4045
|
let i = from;
|
|
3755
|
-
while (i
|
|
4046
|
+
while (!text.atEnd(i)) {
|
|
3756
4047
|
const unit = readTextUnit(text, i, json);
|
|
3757
4048
|
diagnosticScanUnits += 1;
|
|
3758
4049
|
if (!isValue(unitChOf(unit)))
|
|
@@ -3763,6 +4054,7 @@ function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
|
|
|
3763
4054
|
};
|
|
3764
4055
|
const skipBlank = (from) => readRun(from, isRegexSpace);
|
|
3765
4056
|
let valueEnd = 0;
|
|
4057
|
+
let plainEnd = 0;
|
|
3766
4058
|
let nextEq = text.indexOf("=");
|
|
3767
4059
|
let nextColon = text.indexOf(":");
|
|
3768
4060
|
while (nextEq >= 0 || nextColon >= 0) {
|
|
@@ -3775,26 +4067,23 @@ function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
|
|
|
3775
4067
|
op = nextColon;
|
|
3776
4068
|
nextColon = text.indexOf(":", op + 1);
|
|
3777
4069
|
}
|
|
3778
|
-
|
|
3779
|
-
continue;
|
|
4070
|
+
const inValue = op + 1 < plainEnd;
|
|
3780
4071
|
let e = op;
|
|
3781
4072
|
while (e > 0 && isRegexSpace(text.charCodeAt(e - 1)))
|
|
3782
4073
|
e -= 1;
|
|
3783
4074
|
diagnosticScanUnits += op - e;
|
|
3784
4075
|
if (e === 0 || !isRegexWordCode(text.charCodeAt(e - 1)))
|
|
3785
4076
|
continue;
|
|
3786
|
-
const floor = Math.max(0, e - CREDENTIAL_NAME_MAX - 1);
|
|
3787
4077
|
let runStart = e;
|
|
3788
|
-
while (runStart >
|
|
4078
|
+
while (runStart > 0 && isDiagnosticNameCode(text.charCodeAt(runStart - 1)))
|
|
3789
4079
|
runStart -= 1;
|
|
3790
4080
|
diagnosticScanUnits += e - runStart;
|
|
3791
|
-
const runOpen = runStart === floor && floor > 0 && isDiagnosticNameCode(text.charCodeAt(floor - 1));
|
|
3792
4081
|
let nameStart = -1;
|
|
3793
4082
|
let nameTier;
|
|
3794
|
-
for (let q = runStart; q < e && nameStart < 0; q
|
|
3795
|
-
if (
|
|
4083
|
+
for (let q = runStart; q < e && nameStart < 0; q = q === runStart ? Math.max(runStart + 1, e - CREDENTIAL_NAME_MAX) : q + 1) {
|
|
4084
|
+
if (!isRegexWordCode(text.charCodeAt(q)))
|
|
3796
4085
|
continue;
|
|
3797
|
-
const bounded =
|
|
4086
|
+
const bounded = q === runStart || text.charCodeAt(q - 1) === CH_MINUS || deletedAt(q) !== "none";
|
|
3798
4087
|
const tier = bounded ? credentialNameAnchor(text.slice(q, e)) : undefined;
|
|
3799
4088
|
if (tier !== undefined && diagnosticNameSlot(tier)) {
|
|
3800
4089
|
nameStart = q;
|
|
@@ -3803,40 +4092,50 @@ function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
|
|
|
3803
4092
|
}
|
|
3804
4093
|
if (nameStart < 0)
|
|
3805
4094
|
continue;
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
4095
|
+
text.attempt(nameStart);
|
|
4096
|
+
let s;
|
|
4097
|
+
let end;
|
|
4098
|
+
if (inValue) {
|
|
4099
|
+
s = op + 1;
|
|
4100
|
+
end = plainEnd;
|
|
3811
4101
|
}
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
4102
|
+
else {
|
|
4103
|
+
s = skipBlank(op + 1);
|
|
4104
|
+
if (!text.atEnd(s)) {
|
|
4105
|
+
const unit = readTextUnit(text, s, json);
|
|
4106
|
+
if (unitChOf(unit) === CH_QUOTE)
|
|
4107
|
+
s += unitLenOf(unit);
|
|
4108
|
+
}
|
|
4109
|
+
if (text.atEnd(s)) {
|
|
4110
|
+
if (isHead)
|
|
4111
|
+
span(nameStart, text.readEnd(), op, NOT_CLOSED, true);
|
|
4112
|
+
continue;
|
|
4113
|
+
}
|
|
4114
|
+
end = readRun(s, isDiagnosticValueUnit);
|
|
4115
|
+
plainEnd = end;
|
|
3816
4116
|
}
|
|
3817
|
-
let end = readRun(s, isDiagnosticValueUnit);
|
|
3818
4117
|
if (end > s && nameTier === "auth-scheme" && readRun(s, isAsciiLetterCode) === end) {
|
|
3819
4118
|
const k = skipBlank(end);
|
|
3820
|
-
if (k > end &&
|
|
3821
|
-
span(nameStart,
|
|
4119
|
+
if (k > end && isHead && text.atEnd(k)) {
|
|
4120
|
+
span(nameStart, text.readEnd(), op, NOT_CLOSED, true);
|
|
3822
4121
|
continue;
|
|
3823
4122
|
}
|
|
3824
|
-
if (k > end && k
|
|
4123
|
+
if (k > end && !text.atEnd(k)) {
|
|
3825
4124
|
const credEnd = readRun(k, isDiagnosticSchemeValueUnit);
|
|
3826
4125
|
if (credEnd > k)
|
|
3827
4126
|
end = credEnd;
|
|
3828
4127
|
}
|
|
3829
4128
|
}
|
|
3830
|
-
if (end > s) {
|
|
4129
|
+
if (end > s && end > valueEnd) {
|
|
3831
4130
|
span(s, end, op, NOT_CLOSED);
|
|
3832
4131
|
valueEnd = end;
|
|
3833
4132
|
}
|
|
3834
4133
|
}
|
|
3835
4134
|
let schemeEnd = 0;
|
|
3836
|
-
DIAGNOSTIC_SCHEME_RE
|
|
3837
|
-
for (let m = DIAGNOSTIC_SCHEME_RE.exec(text); m !== null; m = DIAGNOSTIC_SCHEME_RE.exec(text)) {
|
|
4135
|
+
for (let m = text.search(DIAGNOSTIC_SCHEME_RE, 0); m !== null; m = text.search(DIAGNOSTIC_SCHEME_RE, m.index + m[0].length)) {
|
|
3838
4136
|
const at = m.index;
|
|
3839
4137
|
const q = at + m[0].length;
|
|
4138
|
+
text.attempt(at);
|
|
3840
4139
|
if (q < schemeEnd)
|
|
3841
4140
|
continue;
|
|
3842
4141
|
if (at > 0 && isRegexWordCode(text.charCodeAt(at - 1)) && deletedAt(at) === "none")
|
|
@@ -3844,9 +4143,9 @@ function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
|
|
|
3844
4143
|
const k = skipBlank(q);
|
|
3845
4144
|
if (k === q && deletedAt(q) !== "blank")
|
|
3846
4145
|
continue;
|
|
3847
|
-
if (k
|
|
4146
|
+
if (text.atEnd(k)) {
|
|
3848
4147
|
if (isHead)
|
|
3849
|
-
span(at,
|
|
4148
|
+
span(at, text.readEnd(), at, NOT_CLOSED, true);
|
|
3850
4149
|
continue;
|
|
3851
4150
|
}
|
|
3852
4151
|
const end = readRun(k, isDiagnosticSchemeValueUnit);
|
|
@@ -3864,12 +4163,14 @@ export function structuralScannerForTest(arm) {
|
|
|
3864
4163
|
};
|
|
3865
4164
|
switch (arm) {
|
|
3866
4165
|
case "json-secret-field":
|
|
3867
|
-
return { declared: new RegExp(JSON_SECRET_FIELD_PATTERN[0].source, JSON_SECRET_FIELD_PATTERN[0].flags), spans: collect(collectJsonSecretFieldSpans) };
|
|
4166
|
+
return { declared: new RegExp(JSON_SECRET_FIELD_PATTERN[0].source, JSON_SECRET_FIELD_PATTERN[0].flags), spans: collect((text, span, isHead) => collectJsonSecretFieldSpans(new ScanReader(text), span, isHead)) };
|
|
3868
4167
|
case "pem-fence":
|
|
3869
|
-
return { declared: new RegExp(PEM_FENCE_PATTERN[0].source, PEM_FENCE_PATTERN[0].flags), spans: collect((text, span, isHead) => collectPemFenceSpans(buildForensicScan(NO_TOKEN_UNITS, NO_ROWS, 1), text, span, isHead)) };
|
|
4168
|
+
return { declared: new RegExp(PEM_FENCE_PATTERN[0].source, PEM_FENCE_PATTERN[0].flags), spans: collect((text, span, isHead) => collectPemFenceSpans(buildForensicScan(NO_TOKEN_UNITS, NO_ROWS, 1, (kind) => delimPositionsOf(text, kind)), new ScanReader(text), span, isHead)) };
|
|
3870
4169
|
}
|
|
3871
4170
|
}
|
|
3872
4171
|
let ppkScanBytes = 0;
|
|
4172
|
+
const TO_END = -1;
|
|
4173
|
+
const EACH_HEAD = -1;
|
|
3873
4174
|
export function ppkScanBytesForTest() { return ppkScanBytes; }
|
|
3874
4175
|
export function resetPpkScanBytesForTest() { ppkScanBytes = 0; }
|
|
3875
4176
|
function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
@@ -3884,14 +4185,14 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3884
4185
|
if (c !== undefined && c >= from)
|
|
3885
4186
|
return c;
|
|
3886
4187
|
const p = text.indexOf(needle, from);
|
|
3887
|
-
ppkScanBytes +=
|
|
4188
|
+
ppkScanBytes += p === -1 ? 0 : p - from;
|
|
3888
4189
|
const v = p === -1 ? Number.POSITIVE_INFINITY : p;
|
|
3889
4190
|
cache.set(needle, v);
|
|
3890
4191
|
return v;
|
|
3891
4192
|
};
|
|
3892
4193
|
const versionEnd = (at) => {
|
|
3893
4194
|
let p = at + HEAD.length;
|
|
3894
|
-
while (
|
|
4195
|
+
while (!text.atEnd(p) && tokenEnd(scan, p) < 0) {
|
|
3895
4196
|
const c = text.charCodeAt(p);
|
|
3896
4197
|
if (c >= 48 && c <= 57)
|
|
3897
4198
|
p += 1;
|
|
@@ -3906,11 +4207,12 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3906
4207
|
};
|
|
3907
4208
|
const isOpenHead = (at) => {
|
|
3908
4209
|
const p = versionEnd(at);
|
|
3909
|
-
return
|
|
4210
|
+
return text.atEnd(p) || (text.atEnd(p + 1) && p > at + HEAD.length && text.charCodeAt(p) === 58);
|
|
3910
4211
|
};
|
|
3911
|
-
const nextVersionedHead = (from) => {
|
|
4212
|
+
const nextVersionedHead = (from, attemptAt) => {
|
|
3912
4213
|
let p = find(HEAD, from);
|
|
3913
4214
|
for (; p !== Number.POSITIVE_INFINITY; p = find(HEAD, p + HEAD.length)) {
|
|
4215
|
+
text.attempt(attemptAt === EACH_HEAD ? p : attemptAt);
|
|
3914
4216
|
const lineEnd = versionedHeadEnd(p);
|
|
3915
4217
|
if (lineEnd >= 0 && !lineHeld(scan, p, lineEnd, readingKey(fam, p)))
|
|
3916
4218
|
break;
|
|
@@ -3919,7 +4221,7 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3919
4221
|
};
|
|
3920
4222
|
const hexRunEnd = (from) => {
|
|
3921
4223
|
let e = from;
|
|
3922
|
-
while (
|
|
4224
|
+
while (!text.atEnd(e) && tokenEnd(scan, e) < 0) {
|
|
3923
4225
|
const c = text.charCodeAt(e);
|
|
3924
4226
|
if ((c >= 48 && c <= 57) || (c >= 97 && c <= 102) || (c >= 65 && c <= 70))
|
|
3925
4227
|
e += 1;
|
|
@@ -3928,12 +4230,13 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3928
4230
|
}
|
|
3929
4231
|
return e;
|
|
3930
4232
|
};
|
|
3931
|
-
let at = nextVersionedHead(0);
|
|
4233
|
+
let at = nextVersionedHead(0, EACH_HEAD);
|
|
3932
4234
|
while (at !== Number.POSITIVE_INFINITY) {
|
|
3933
4235
|
scan.self = readingKey(fam, at);
|
|
4236
|
+
text.attempt(at);
|
|
3934
4237
|
let pos = at + HEAD.length + 1;
|
|
3935
4238
|
let closeAt = NOT_CLOSED;
|
|
3936
|
-
let end =
|
|
4239
|
+
let end = TO_END;
|
|
3937
4240
|
let ateToEnd = !isHead;
|
|
3938
4241
|
let open = false;
|
|
3939
4242
|
for (;;) {
|
|
@@ -3954,7 +4257,7 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3954
4257
|
pos = hexStart;
|
|
3955
4258
|
continue;
|
|
3956
4259
|
}
|
|
3957
|
-
const limit = nextVersionedHead(hexEnd);
|
|
4260
|
+
const limit = nextVersionedHead(hexEnd, at);
|
|
3958
4261
|
const straggler = Math.min(find(LINES, hexEnd), find(MAC, hexEnd), find(HASH, hexEnd));
|
|
3959
4262
|
let gapBlank = true;
|
|
3960
4263
|
if (limit !== Number.POSITIVE_INFINITY) {
|
|
@@ -3968,7 +4271,7 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3968
4271
|
}
|
|
3969
4272
|
const undecided = isHead && limit === Number.POSITIVE_INFINITY;
|
|
3970
4273
|
ateToEnd = straggler < limit || !gapBlank;
|
|
3971
|
-
end = ateToEnd || undecided ?
|
|
4274
|
+
end = ateToEnd || undecided ? TO_END : hexEnd;
|
|
3972
4275
|
open = undecided;
|
|
3973
4276
|
if (end === hexEnd)
|
|
3974
4277
|
closeAt = term;
|
|
@@ -3976,14 +4279,24 @@ function collectPpkContainerSpans(scan, text, eat, span, isHead) {
|
|
|
3976
4279
|
}
|
|
3977
4280
|
if (ateToEnd && eat !== undefined && eat.from < 0) {
|
|
3978
4281
|
eat.from = at;
|
|
3979
|
-
eat.len = text.
|
|
4282
|
+
eat.len = text.readEnd();
|
|
3980
4283
|
}
|
|
3981
|
-
span(at, end, at, closeAt, open);
|
|
3982
|
-
at = end
|
|
4284
|
+
span(at, end === TO_END ? text.readEnd() : end, at, closeAt, open);
|
|
4285
|
+
at = end === TO_END ? Number.POSITIVE_INFINITY : nextVersionedHead(end, EACH_HEAD);
|
|
3983
4286
|
}
|
|
3984
4287
|
const last = isHead ? text.lastIndexOf(HEAD) : -1;
|
|
3985
|
-
if (last >= 0
|
|
3986
|
-
|
|
4288
|
+
if (last >= 0)
|
|
4289
|
+
text.attempt(last);
|
|
4290
|
+
if (last >= 0 && isOpenHead(last) && !lineHeld(scan, last, text.readEnd(), readingKey(fam, last)))
|
|
4291
|
+
span(last, text.readEnd(), last, NOT_CLOSED, true);
|
|
4292
|
+
}
|
|
4293
|
+
function anchoredHeadOf(prior) {
|
|
4294
|
+
switch (prior.kind) {
|
|
4295
|
+
case "anchored":
|
|
4296
|
+
return { kind: "anchors", anchors: prior.anchors };
|
|
4297
|
+
case "bounded":
|
|
4298
|
+
throw new Error("redact: a bounded arm declares no anchor literal to read its head from");
|
|
4299
|
+
}
|
|
3987
4300
|
}
|
|
3988
4301
|
const NO_GAP = (_unit) => false;
|
|
3989
4302
|
const armPool = (() => {
|
|
@@ -3993,6 +4306,9 @@ const armPool = (() => {
|
|
|
3993
4306
|
throw new Error(`redact: arm-pool replacement ${JSON.stringify(token)} may only use a leading $1 (the run kept outside the span)`);
|
|
3994
4307
|
return body;
|
|
3995
4308
|
};
|
|
4309
|
+
const headUnderivable = (re) => {
|
|
4310
|
+
throw new Error(`redact: regex arm /${re.source}/ has no derivable head — the live frontier cannot tell where an attempt that reads past the end of the text starts`);
|
|
4311
|
+
};
|
|
3996
4312
|
const regexMember = ([re, token], rank, order) => {
|
|
3997
4313
|
if (token.startsWith("$1"))
|
|
3998
4314
|
throw new Error(`redact: regex arm /${re.source}/ cannot carry an outside-span $1 prefix — that form belongs to the structural scanners`);
|
|
@@ -4015,7 +4331,7 @@ const armPool = (() => {
|
|
|
4015
4331
|
phase: 1,
|
|
4016
4332
|
lexical: LEXICAL_KEYWORD_ARMS.has(re),
|
|
4017
4333
|
diagnosticOnly: false,
|
|
4018
|
-
collect: (text, _json, _eat, out, isHead) => {
|
|
4334
|
+
collect: (text, _view, _json, _eat, out, isHead) => {
|
|
4019
4335
|
if (boundary === undefined)
|
|
4020
4336
|
collectRegexSpans(arm, text, out);
|
|
4021
4337
|
else
|
|
@@ -4032,9 +4348,10 @@ const armPool = (() => {
|
|
|
4032
4348
|
family: "prose",
|
|
4033
4349
|
reach: regexDecisionReach(re, LEXICAL_KEYWORD_ARMS.has(re)),
|
|
4034
4350
|
prior: { kind: "bounded", gap: keywordTail === undefined ? NO_GAP : (c) => keywordTail.isSeparator(String.fromCharCode(c)) },
|
|
4351
|
+
head: { kind: "units", seqs: keywordTail !== undefined ? keywordTail.forms.map((f) => [...f].map((ch) => codeUnitMembers(ch))) : d.src !== undefined ? expandHeadUnits(d.src, re.flags) : headUnderivable(re) },
|
|
4035
4352
|
};
|
|
4036
4353
|
};
|
|
4037
|
-
const scannerMember = (token, order, arm, reach, family, prior, rank = ARM_RANK.structural, lexical = false, diagnosticOnly = false) => {
|
|
4354
|
+
const scannerMember = (token, order, arm, reach, family, prior, head, rank = ARM_RANK.structural, lexical = false, diagnosticOnly = false) => {
|
|
4038
4355
|
const repl = spanRepl(token);
|
|
4039
4356
|
return {
|
|
4040
4357
|
token,
|
|
@@ -4043,16 +4360,17 @@ const armPool = (() => {
|
|
|
4043
4360
|
phase: 1,
|
|
4044
4361
|
lexical,
|
|
4045
4362
|
diagnosticOnly,
|
|
4046
|
-
collect: (
|
|
4363
|
+
collect: (_text, view, json, eat, out, isHead, deletedAt) => arm(view, json, eat, (start, end, anchor, closeAt, undecided, r = repl) => out.push(undecided === true ? { start, end, repl: r, rank, order, undecided, anchor, closeAt } : { start, end, repl: r, rank, order, anchor, closeAt }), isHead, deletedAt),
|
|
4047
4364
|
retry: undefined,
|
|
4048
4365
|
headSrc: undefined,
|
|
4049
4366
|
headFirst: undefined,
|
|
4050
4367
|
family,
|
|
4051
4368
|
reach,
|
|
4052
4369
|
prior,
|
|
4370
|
+
head,
|
|
4053
4371
|
};
|
|
4054
4372
|
};
|
|
4055
|
-
const forensicMember = (token, order, arm, reach, family, prior, rank = ARM_RANK.structural, lexical = false) => {
|
|
4373
|
+
const forensicMember = (token, order, arm, reach, family, grain, prior, head, rank = ARM_RANK.structural, lexical = false) => {
|
|
4056
4374
|
const repl = spanRepl(token);
|
|
4057
4375
|
return {
|
|
4058
4376
|
token,
|
|
@@ -4061,41 +4379,47 @@ const armPool = (() => {
|
|
|
4061
4379
|
phase: 2,
|
|
4062
4380
|
lexical,
|
|
4063
4381
|
diagnosticOnly: false,
|
|
4064
|
-
collect: (scan,
|
|
4382
|
+
collect: (scan, view, json, eat, out, isHead) => arm(scan, view, json, eat, (start, end, anchor, closeAt, undecided, r = repl) => out.push(undecided === true ? { start, end, repl: r, rank, order, undecided, anchor, closeAt } : { start, end, repl: r, rank, order, anchor, closeAt }), isHead),
|
|
4065
4383
|
retry: undefined,
|
|
4066
4384
|
headSrc: undefined,
|
|
4067
4385
|
headFirst: undefined,
|
|
4068
4386
|
family,
|
|
4069
4387
|
repl,
|
|
4388
|
+
grain,
|
|
4070
4389
|
reach,
|
|
4071
4390
|
prior,
|
|
4391
|
+
head,
|
|
4072
4392
|
};
|
|
4073
4393
|
};
|
|
4394
|
+
const PEM_ARMOR_PRIOR = { kind: "anchored", anchors: [PEM_FENCE_OPEN, PEM_END_OPEN] };
|
|
4395
|
+
const SSH2_ARMOR_PRIOR = { kind: "anchored", anchors: [SSH2_FENCE_OPEN, SSH2_FENCE_CLOSE] };
|
|
4396
|
+
const PPK_CONTAINER_PRIOR = { kind: "anchored", anchors: [PPK_FILE_HEAD] };
|
|
4397
|
+
const HEADLESS_PPK_PRIOR = { kind: "anchored", anchors: [PPK_LINES_FIELD] };
|
|
4074
4398
|
const structuralScannerMember = (row, order) => {
|
|
4075
4399
|
if (row === PEM_FENCE_PATTERN)
|
|
4076
|
-
return forensicMember(row[1], order, (scan, text, _json, _eat, span, isHead) => collectPemFenceSpans(scan, text, span, isHead), PEM_FENCE_OPEN.length, "pem-armor",
|
|
4400
|
+
return forensicMember(row[1], order, (scan, text, _json, _eat, span, isHead) => collectPemFenceSpans(scan, text, span, isHead), PEM_FENCE_OPEN.length, "pem-armor", "arm", PEM_ARMOR_PRIOR, anchoredHeadOf(PEM_ARMOR_PRIOR));
|
|
4077
4401
|
if (row === SSH2_FENCE_PATTERN)
|
|
4078
|
-
return forensicMember(row[1], order, (scan, text, json, _eat, span, isHead) => collectSsh2FenceSpans(scan, text, json, span, isHead), SSH2_FENCE_OPEN.length, "ssh2-armor",
|
|
4402
|
+
return forensicMember(row[1], order, (scan, text, json, _eat, span, isHead) => collectSsh2FenceSpans(scan, text, json, span, isHead), SSH2_FENCE_OPEN.length, "ssh2-armor", "arm", SSH2_ARMOR_PRIOR, anchoredHeadOf(SSH2_ARMOR_PRIOR));
|
|
4079
4403
|
if (row === URL_CREDENTIAL_PATTERN)
|
|
4080
|
-
return forensicMember(row[1], order, (scan, text, json, _eat, span, isHead) => collectUrlCredentialSpans(scan, text, json, span, isHead), "://".length, "url", { kind: "bounded", gap: NO_GAP });
|
|
4404
|
+
return forensicMember(row[1], order, (scan, text, json, _eat, span, isHead) => collectUrlCredentialSpans(scan, text, json, span, isHead), "://".length, "url", "segment", { kind: "bounded", gap: NO_GAP }, { kind: "anchors", anchors: ["://"] });
|
|
4081
4405
|
if (row === JSON_SECRET_FIELD_PATTERN)
|
|
4082
|
-
return scannerMember(row[1], order, (text, _json, _eat, span, isHead) => collectJsonSecretFieldSpans(text, span, isHead),
|
|
4406
|
+
return scannerMember(row[1], order, (text, _json, _eat, span, isHead) => collectJsonSecretFieldSpans(text, span, isHead), JSON_FIELD_HEAD_MAX, "json-field", { kind: "bounded", gap: isRegexSpace }, { kind: "anchors", anchors: [JSON_FIELD_ANCHOR] });
|
|
4083
4407
|
throw new Error(`redact: structural row /${row[0].source}/ has no hand-written scanner — structural grammars are declared as regexes but never executed as one (S-102 / S-265)`);
|
|
4084
4408
|
};
|
|
4085
4409
|
const members = [];
|
|
4086
4410
|
for (const row of STRUCTURAL_SECRET_PATTERNS)
|
|
4087
4411
|
members.push(structuralScannerMember(row, members.length));
|
|
4088
|
-
members.push(forensicMember(PPK_CONTAINER_TOKEN, members.length, (scan, text, _json, eat, span, isHead) => collectPpkContainerSpans(scan, text, eat, span, isHead), PPK_FILE_HEAD.length, "putty-ppk",
|
|
4089
|
-
members.push(forensicMember(PEM_FRAGMENT_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectPemFragmentSpans(scan, text, json, span, isHead), PEM_FENCE_OPEN.length, "pem-armor",
|
|
4090
|
-
members.push(forensicMember(HEADLESS_PPK_TOKEN, members.length, (scan, text, _json, _eat, span, isHead) => collectHeadlessPpkSpans(scan, text, span, isHead), PPK_LINES_FIELD.length, "putty-ppk",
|
|
4091
|
-
members.push(forensicMember(ANCHORED_VALUE_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectAnchoredValueSpans(scan, text, json, span, isHead), Math.max(BEARER_VALUE_MIN, BARE_WORD_MAX + 1, STRONG_AUTH_SCHEME_MAX + 1), "anchor", { kind: "bounded", gap: (c) => isInlineSpaceUnit(c) || isSchemeDelimiterCode(c) }, ARM_RANK.keyword, true));
|
|
4412
|
+
members.push(forensicMember(PPK_CONTAINER_TOKEN, members.length, (scan, text, _json, eat, span, isHead) => collectPpkContainerSpans(scan, text, eat, span, isHead), PPK_FILE_HEAD.length, "putty-ppk", "arm", PPK_CONTAINER_PRIOR, anchoredHeadOf(PPK_CONTAINER_PRIOR)));
|
|
4413
|
+
members.push(forensicMember(PEM_FRAGMENT_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectPemFragmentSpans(scan, text, json, span, isHead), PEM_FENCE_OPEN.length, "pem-armor", "arm", PEM_ARMOR_PRIOR, anchoredHeadOf(PEM_ARMOR_PRIOR)));
|
|
4414
|
+
members.push(forensicMember(HEADLESS_PPK_TOKEN, members.length, (scan, text, _json, _eat, span, isHead) => collectHeadlessPpkSpans(scan, text, span, isHead), PPK_LINES_FIELD.length, "putty-ppk", "arm", HEADLESS_PPK_PRIOR, anchoredHeadOf(HEADLESS_PPK_PRIOR)));
|
|
4415
|
+
members.push(forensicMember(ANCHORED_VALUE_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectAnchoredValueSpans(scan, text, json, span, isHead), Math.max(BEARER_VALUE_MIN, BARE_WORD_MAX + 1, STRONG_AUTH_SCHEME_MAX + 1), "anchor", "segment", { kind: "bounded", gap: (c) => isInlineSpaceUnit(c) || isSchemeDelimiterCode(c) }, { kind: "anchors", anchors: ["=", ":"] }, ARM_RANK.keyword, true));
|
|
4092
4416
|
for (const row of KEYWORD_SECRET_PATTERNS)
|
|
4093
4417
|
members.push(regexMember(row, ARM_RANK.keyword, members.length));
|
|
4094
4418
|
for (const row of SHAPE_SECRET_PATTERNS)
|
|
4095
4419
|
members.push(regexMember(row, ARM_RANK.shape, members.length));
|
|
4096
4420
|
for (const row of FRAGMENT_SECRET_PATTERNS)
|
|
4097
4421
|
members.push(regexMember(row, ARM_RANK.fragment, members.length));
|
|
4098
|
-
members.push(scannerMember(ANCHORED_VALUE_TOKEN, members.length, (text, json, _eat, span, isHead, deletedAt) => collectDiagnosticValueSpans(text, json, span, isHead, deletedAt), Math.max(CREDENTIAL_NAME_MAX, STRONG_AUTH_SCHEME_MAX) + 2, "prose", { kind: "bounded", gap: isRegexSpace }, ARM_RANK.keyword, true, true));
|
|
4422
|
+
members.push(scannerMember(ANCHORED_VALUE_TOKEN, members.length, (text, json, _eat, span, isHead, deletedAt) => collectDiagnosticValueSpans(text, json, span, isHead, deletedAt), Math.max(CREDENTIAL_NAME_MAX, STRONG_AUTH_SCHEME_MAX) + 2, "prose", { kind: "bounded", gap: isRegexSpace }, { kind: "anchors", anchors: ["=", ":"] }, ARM_RANK.keyword, true, true));
|
|
4099
4423
|
for (const [re] of KEYWORD_SECRET_PATTERNS) {
|
|
4100
4424
|
if (!LEXICAL_KEYWORD_ARMS.has(re))
|
|
4101
4425
|
throw new Error(`redact: keyword arm /${re.source}/ is not registered as lexical — build it with keywordArm() so the bounded-unit scope can exclude it`);
|
|
@@ -4128,11 +4452,51 @@ const armPool = (() => {
|
|
|
4128
4452
|
poolArmCount = members.length;
|
|
4129
4453
|
poolBoundaryArmCount = retryMembers.length;
|
|
4130
4454
|
const reaches = members.map((m) => ({ token: m.token, order: m.order, reach: m.reach }));
|
|
4455
|
+
const viewOpenOf = (text, lane, spans, scanned) => {
|
|
4456
|
+
const n = text.length;
|
|
4457
|
+
let open = scanned;
|
|
4458
|
+
const visit = (m) => {
|
|
4459
|
+
const h = m.head;
|
|
4460
|
+
switch (h.kind) {
|
|
4461
|
+
case "units":
|
|
4462
|
+
for (let p = Math.max(0, n - m.reach); p < open; p++) {
|
|
4463
|
+
if (headFeasibleAt(h.seqs, text, p)) {
|
|
4464
|
+
open = p;
|
|
4465
|
+
break;
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
return;
|
|
4469
|
+
case "anchors":
|
|
4470
|
+
for (const a of h.anchors) {
|
|
4471
|
+
for (let k = Math.min(a.length - 1, n); k > 0 && n - k < open; k--) {
|
|
4472
|
+
if (text.endsWith(a.slice(0, k))) {
|
|
4473
|
+
open = n - k;
|
|
4474
|
+
break;
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
return;
|
|
4479
|
+
default: {
|
|
4480
|
+
const unhandled = h;
|
|
4481
|
+
throw new Error(`redact: unhandled head reading ${String(unhandled)}`);
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
};
|
|
4485
|
+
for (const m of lane.phase1)
|
|
4486
|
+
visit(m);
|
|
4487
|
+
for (const m of lane.phase2)
|
|
4488
|
+
visit(m);
|
|
4489
|
+
for (const sp of spans)
|
|
4490
|
+
if (sp.end >= n && sp.start < open && members[sp.order].head.kind === "units")
|
|
4491
|
+
open = sp.start;
|
|
4492
|
+
return open;
|
|
4493
|
+
};
|
|
4131
4494
|
const run = (text, wantCount, json, eat, scope, reach, engineMarked, deletedAt) => {
|
|
4132
4495
|
readings += 1;
|
|
4133
4496
|
const isHead = reach !== undefined;
|
|
4134
4497
|
const lane = LANES[scope];
|
|
4135
4498
|
const spans = [];
|
|
4499
|
+
const view = new ScanReader(text);
|
|
4136
4500
|
let tried;
|
|
4137
4501
|
const untriedFrom = (nu, p) => {
|
|
4138
4502
|
let q = p;
|
|
@@ -4182,11 +4546,14 @@ const armPool = (() => {
|
|
|
4182
4546
|
at = freshCovered(before);
|
|
4183
4547
|
}
|
|
4184
4548
|
};
|
|
4185
|
-
for (const m of lane.phase1)
|
|
4186
|
-
|
|
4549
|
+
for (const m of lane.phase1) {
|
|
4550
|
+
view.begin();
|
|
4551
|
+
m.collect(text, view, json, eat, spans, isHead, deletedAt);
|
|
4552
|
+
}
|
|
4187
4553
|
closeCoveragePositions(0);
|
|
4554
|
+
let evidence;
|
|
4188
4555
|
if (lane.phase2.length > 0) {
|
|
4189
|
-
const scan = buildForensicScan(tokenUnits(text), buildEvidenceRows(text), lane.phase2.length);
|
|
4556
|
+
const scan = buildForensicScan(tokenUnits(text), buildEvidenceRows(text), lane.phase2.length, (kind) => delimPositionsOf(text, kind));
|
|
4190
4557
|
const reuse = forensicRescanMode === "incremental";
|
|
4191
4558
|
const foot = scan.armFoot;
|
|
4192
4559
|
let dirty;
|
|
@@ -4205,15 +4572,29 @@ const armPool = (() => {
|
|
|
4205
4572
|
scan.self = NO_SELF;
|
|
4206
4573
|
scan.footLo = FOOT_NONE;
|
|
4207
4574
|
scan.footHi = -1;
|
|
4208
|
-
lane.phase2[j]
|
|
4575
|
+
const arm = lane.phase2[j];
|
|
4576
|
+
view.begin();
|
|
4577
|
+
arm.collect(scan, view, json, level === 0 ? eat : undefined, spans, isHead);
|
|
4209
4578
|
foot[2 * j] = scan.footLo;
|
|
4210
4579
|
foot[2 * j + 1] = scan.footHi;
|
|
4211
4580
|
forensicRuns += 1;
|
|
4581
|
+
switch (arm.grain) {
|
|
4582
|
+
case "arm":
|
|
4583
|
+
noteExecution(scan, scan.footLo, scan.footHi, scan.footLo);
|
|
4584
|
+
break;
|
|
4585
|
+
case "segment":
|
|
4586
|
+
break;
|
|
4587
|
+
default: {
|
|
4588
|
+
const unhandled = arm.grain;
|
|
4589
|
+
throw new Error(`redact: unhandled evidence grain ${String(unhandled)}`);
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4212
4592
|
}
|
|
4213
4593
|
closeCoveragePositions(before);
|
|
4214
4594
|
forensicLevels += 1;
|
|
4215
4595
|
const grown = foldEvidenceRows(scan.rows, spans, folded, (o) => familyCodeOfOrder[o]);
|
|
4216
4596
|
folded = spans.length;
|
|
4597
|
+
evidence = { execs: scan.execs, rows: grown.next };
|
|
4217
4598
|
if (grown.dirty.starts.length === 0)
|
|
4218
4599
|
break;
|
|
4219
4600
|
if (level + 1 >= FORENSIC_LEVEL_MAX) {
|
|
@@ -4236,9 +4617,12 @@ const armPool = (() => {
|
|
|
4236
4617
|
}
|
|
4237
4618
|
poolSpanCount += spans.length;
|
|
4238
4619
|
const survives = (sp) => !engineMarked(sp.start, sp.end, sp.repl) && (sp.undecided !== true || reach === undefined || reach(sp.start));
|
|
4239
|
-
const
|
|
4620
|
+
const cover = spans.filter(survives);
|
|
4621
|
+
const kept = resolveSpanOverlaps(cover);
|
|
4622
|
+
const open = isHead ? viewOpenOf(text, lane, spans, view.open) : text.length;
|
|
4623
|
+
const unattributed = view.unattributed;
|
|
4240
4624
|
if (!wantCount || kept.length === 0)
|
|
4241
|
-
return { hits: NO_HITS, kept };
|
|
4625
|
+
return { hits: NO_HITS, kept, cover, evidence, open, unattributed };
|
|
4242
4626
|
const tokenOf = (sp) => members[sp.order].token;
|
|
4243
4627
|
const strong = spans.filter((sp) => armOfToken(tokenOf(sp)) === "full" && survives(sp)).sort((a, b) => a.start - b.start);
|
|
4244
4628
|
const byArmedToken = new Map();
|
|
@@ -4260,9 +4644,9 @@ const armPool = (() => {
|
|
|
4260
4644
|
cur.count += 1;
|
|
4261
4645
|
stamped.push({ ...sp, hit: { token, arm } });
|
|
4262
4646
|
}
|
|
4263
|
-
return { hits: [...byArmedToken.values()].map(({ token, arm, count }) => ({ label: labelOfToken(token), count, arm })), kept: stamped };
|
|
4647
|
+
return { hits: [...byArmedToken.values()].map(({ token, arm, count }) => ({ label: labelOfToken(token), count, arm })), kept: stamped, cover, evidence, open, unattributed };
|
|
4264
4648
|
};
|
|
4265
|
-
return Object.assign(run, { reaches,
|
|
4649
|
+
return Object.assign(run, { reaches, maxDecisionReach: Math.max(...reaches.map((r) => r.reach)), priors: members.map((m) => m.prior) });
|
|
4266
4650
|
})();
|
|
4267
4651
|
let onRedaction;
|
|
4268
4652
|
export function setRedactionObserver(fn) {
|
|
@@ -4286,9 +4670,9 @@ export const WHOLE_EXTENT = { kind: "whole" };
|
|
|
4286
4670
|
function invisibleClassesOf(layout) {
|
|
4287
4671
|
switch (layout) {
|
|
4288
4672
|
case "multi-line":
|
|
4289
|
-
return SPELLED_FORMAT | SPELLED_CONTROL | RAW_CONTROL;
|
|
4673
|
+
return SPELLED_FORMAT | SPELLED_CONTROL | RAW_CONTROL | RAW_IGNORABLE;
|
|
4290
4674
|
case "single-line":
|
|
4291
|
-
return SPELLED_FORMAT | SPELLED_CONTROL | RAW_CONTROL | RAW_WHITESPACE;
|
|
4675
|
+
return SPELLED_FORMAT | SPELLED_CONTROL | RAW_CONTROL | RAW_WHITESPACE | RAW_IGNORABLE;
|
|
4292
4676
|
default: {
|
|
4293
4677
|
const unhandled = layout;
|
|
4294
4678
|
throw new Error(`redact: unhandled layout ${String(unhandled)}`);
|
|
@@ -4329,14 +4713,19 @@ export function readingHeadEnd(text, layout, units, from = 0) {
|
|
|
4329
4713
|
}
|
|
4330
4714
|
return text.length;
|
|
4331
4715
|
}
|
|
4332
|
-
function runRedaction(text, observe, json, wantHits, scope, layout, extent, observeFrom = 0) {
|
|
4716
|
+
function runRedaction(text, observe, json, wantHits, scope, layout, extent, observeFrom = 0, joints = NO_JOINTS) {
|
|
4333
4717
|
scannedUnits += text.length;
|
|
4334
4718
|
const wantCount = wantHits || (onRedaction !== undefined && observe);
|
|
4335
4719
|
const eat = observe ? { from: -1, len: 0, capFrom: -1, capLen: 0 } : undefined;
|
|
4336
4720
|
let spans = [];
|
|
4721
|
+
const cover = [];
|
|
4337
4722
|
let hits = NO_HITS;
|
|
4338
4723
|
let readsSoFar = 0;
|
|
4339
4724
|
let unioned = false;
|
|
4725
|
+
const evidence = [];
|
|
4726
|
+
let lattice = text.length;
|
|
4727
|
+
let viewOpen = text.length;
|
|
4728
|
+
let unattributed = false;
|
|
4340
4729
|
const read = (layers, view) => {
|
|
4341
4730
|
const toOriginal = createViewToOriginal(layers);
|
|
4342
4731
|
const reach = extent.kind === "head" ? (viewStart) => toOriginal.start(viewStart) < extent.emitEnd : undefined;
|
|
@@ -4355,7 +4744,17 @@ function runRedaction(text, observe, json, wantHits, scope, layout, extent, obse
|
|
|
4355
4744
|
};
|
|
4356
4745
|
const r = applyRules(view, wantCount, json, eat, scope, reach, engineMarked, deletedAt);
|
|
4357
4746
|
forgetEscapedSeparatorTails();
|
|
4747
|
+
if (r.evidence !== undefined && (r.evidence.execs.length > 0 || r.evidence.rows.starts.length > 0)) {
|
|
4748
|
+
const viewLength = view.length;
|
|
4749
|
+
evidence.push({ execs: r.evidence.execs, rows: r.evidence.rows, at: (v) => (v >= viewLength ? text.length : toOriginal.start(v)) });
|
|
4750
|
+
}
|
|
4751
|
+
if (r.open < view.length)
|
|
4752
|
+
viewOpen = Math.min(viewOpen, toOriginal.start(r.open));
|
|
4753
|
+
if (r.unattributed)
|
|
4754
|
+
unattributed = true;
|
|
4358
4755
|
readsSoFar += 1;
|
|
4756
|
+
for (const sp of toOriginal.spans(r.cover))
|
|
4757
|
+
cover.push(sp);
|
|
4359
4758
|
if (readsSoFar === 1) {
|
|
4360
4759
|
spans = toOriginal.spans(r.kept);
|
|
4361
4760
|
hits = r.hits;
|
|
@@ -4372,6 +4771,7 @@ function runRedaction(text, observe, json, wantHits, scope, layout, extent, obse
|
|
|
4372
4771
|
const rfold = deleteInvisibleCharacters(text, raw, rmask);
|
|
4373
4772
|
const normalized = normalizeForRedaction(rfold.text);
|
|
4374
4773
|
const spelled = collectSpelledCuts(normalized);
|
|
4774
|
+
lattice = Math.min(lattice, latticeOpenOf(text.length, rfold, normalized, spelled.open));
|
|
4375
4775
|
for (let smask = 0;; smask = (smask - spelled.present) & spelled.present) {
|
|
4376
4776
|
const sfold = deleteInvisibleCharacters(normalized, spelled, smask);
|
|
4377
4777
|
read([{ fold: sfold }, { input: rfold.text, view: normalized }, { fold: rfold }], sfold.text);
|
|
@@ -4387,9 +4787,21 @@ function runRedaction(text, observe, json, wantHits, scope, layout, extent, obse
|
|
|
4387
4787
|
recordFailOpen("server.redact.ppk-eat-to-end", `from=${eat.from} len=${eat.len}`);
|
|
4388
4788
|
if (eat !== undefined && eat.capFrom >= 0)
|
|
4389
4789
|
recordFailOpen("server.redact.forensic-level-cap", `from=${eat.capFrom} len=${eat.capLen}`);
|
|
4790
|
+
if (observe && unattributed)
|
|
4791
|
+
recordFailOpen("server.redact.scan-view-unattributed", `len=${text.length}`);
|
|
4390
4792
|
if (observe)
|
|
4391
4793
|
reportHits(observeFrom === 0 ? hits : hitsOfSpans(spans.filter((sp) => sp.end > observeFrom)));
|
|
4392
|
-
|
|
4794
|
+
const groups = mergeRedactionSpans(cover, poolTie, joints);
|
|
4795
|
+
return { text: renderRedactionSpans(text, groups, 0, text.length), hits, spans: groups, crossed: jointsCrossedBy(spans, joints), evidence, lattice, view: viewOpen };
|
|
4796
|
+
}
|
|
4797
|
+
function latticeOpenOf(n, rfold, normalized, open) {
|
|
4798
|
+
let at = n;
|
|
4799
|
+
if (open >= 0)
|
|
4800
|
+
at = createViewToOriginal([{ input: rfold.text, view: normalized }, { fold: rfold }]).start(open);
|
|
4801
|
+
const last = rfold.text.length - 1;
|
|
4802
|
+
if (last >= 0 && (rfold.text.charCodeAt(last) & 0xfc00) === 0xd800)
|
|
4803
|
+
at = Math.min(at, createViewToOriginal([{ fold: rfold }]).start(last));
|
|
4804
|
+
return at;
|
|
4393
4805
|
}
|
|
4394
4806
|
function hitsOfSpans(spans) {
|
|
4395
4807
|
const by = new Map();
|
|
@@ -4427,8 +4839,8 @@ export function redactSecrets(text, opts) {
|
|
|
4427
4839
|
if (before === "")
|
|
4428
4840
|
return runRedaction(text, opts?.observe ?? true, opts?.json === true, false, "free-text", "multi-line", WHOLE_EXTENT).text;
|
|
4429
4841
|
const whole = before + text;
|
|
4430
|
-
const r = runRedaction(whole, opts?.observe ?? true, opts?.json === true, false, "free-text", "multi-line", WHOLE_EXTENT, before.length);
|
|
4431
|
-
return
|
|
4842
|
+
const r = runRedaction(whole, opts?.observe ?? true, opts?.json === true, false, "free-text", "multi-line", WHOLE_EXTENT, before.length, [before.length]);
|
|
4843
|
+
return renderRedactionSpans(whole, r.spans, before.length, whole.length);
|
|
4432
4844
|
}
|
|
4433
4845
|
export function redactSecretsWithArms(text, opts) {
|
|
4434
4846
|
const r = runRedaction(text, opts?.observe ?? true, opts?.json === true, true, "free-text", "multi-line", WHOLE_EXTENT);
|
|
@@ -4438,21 +4850,136 @@ export function redactionSpansForTest(text, opts) {
|
|
|
4438
4850
|
const r = runRedaction(text, false, opts?.json === true, false, opts?.scope ?? "free-text", "multi-line", WHOLE_EXTENT);
|
|
4439
4851
|
return { text: r.text, spans: r.spans.map((sp) => ({ start: sp.start, end: sp.end })) };
|
|
4440
4852
|
}
|
|
4441
|
-
export function proposeRedactionSpans(text, scope, layout, extent) {
|
|
4442
|
-
return runRedaction(text, true,
|
|
4853
|
+
export function proposeRedactionSpans(text, scope, layout, extent, json) {
|
|
4854
|
+
return runRedaction(text, true, json, false, scope, layout, extent).spans.map((sp) => ({ start: sp.start, end: sp.end, repl: sp.repl }));
|
|
4443
4855
|
}
|
|
4444
|
-
export const
|
|
4856
|
+
export const MAX_DECISION_REACH = armPool.maxDecisionReach;
|
|
4445
4857
|
export function regexDecisionReachForTest(re, lexical) {
|
|
4446
4858
|
return regexDecisionReach(re, lexical);
|
|
4447
4859
|
}
|
|
4448
|
-
export function
|
|
4860
|
+
export function decisionReachForTest() {
|
|
4449
4861
|
return armPool.reaches;
|
|
4450
4862
|
}
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4863
|
+
const FRONTIER_TERMS = {
|
|
4864
|
+
view: (m) => m.view,
|
|
4865
|
+
lattice: (m) => m.lattice,
|
|
4866
|
+
token: (m) => m.token,
|
|
4867
|
+
evidence: (m, f) => m.evidence(f),
|
|
4868
|
+
coverage: (m) => m.n,
|
|
4869
|
+
};
|
|
4870
|
+
const READ_PORTS = Object.keys(FRONTIER_TERMS);
|
|
4871
|
+
function settledFrontier(m) {
|
|
4872
|
+
let f = m.n;
|
|
4873
|
+
for (;;) {
|
|
4874
|
+
let next = f;
|
|
4875
|
+
for (const k of READ_PORTS)
|
|
4876
|
+
next = Math.min(next, FRONTIER_TERMS[k](m, next));
|
|
4877
|
+
if (next >= f)
|
|
4878
|
+
return f;
|
|
4879
|
+
f = next;
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
function tokenTailOpen(text) {
|
|
4883
|
+
const n = text.length;
|
|
4884
|
+
const p = text.lastIndexOf("«");
|
|
4885
|
+
if (p < 0)
|
|
4886
|
+
return n;
|
|
4887
|
+
const e = tokenUnitEnd(text, p);
|
|
4888
|
+
if (e < 0)
|
|
4889
|
+
return n - p < TOKEN_UNIT_REACH && text.indexOf("»", p) < 0 ? p : n;
|
|
4890
|
+
if (e !== n)
|
|
4891
|
+
return n;
|
|
4892
|
+
let start = p;
|
|
4893
|
+
while (start > 0) {
|
|
4894
|
+
const q = text.lastIndexOf("«", start - 1);
|
|
4895
|
+
if (q < 0 || tokenUnitEnd(text, q) < start)
|
|
4896
|
+
break;
|
|
4897
|
+
start = q;
|
|
4898
|
+
}
|
|
4899
|
+
return start;
|
|
4900
|
+
}
|
|
4901
|
+
const TOKEN_UNIT_REACH = regexDecisionReach(TOKEN_UNIT_Y, false);
|
|
4902
|
+
function createEvidenceFrontier(readings) {
|
|
4903
|
+
const prepared = readings.filter((r) => r.execs.length > 0).map((r) => {
|
|
4904
|
+
const E = r.execs.length / 3;
|
|
4905
|
+
const order = Array.from({ length: E }, (_, i) => i);
|
|
4906
|
+
const hi = Float64Array.from(order, (i) => r.at(r.execs[3 * i + 1]));
|
|
4907
|
+
const from = Float64Array.from(order, (i) => r.at(r.execs[3 * i + 2]));
|
|
4908
|
+
order.sort((x, y) => hi[y] - hi[x]);
|
|
4909
|
+
const t = r.rows;
|
|
4910
|
+
const iv = [];
|
|
4911
|
+
for (let k = 0; k < t.starts.length; k++) {
|
|
4912
|
+
const s = r.at(t.starts[k]);
|
|
4913
|
+
const c = t.closeAt[k];
|
|
4914
|
+
const d = Math.max(r.at(t.ends[k] - 1) + 1, c >= 0 ? r.at(c) + 1 : 0);
|
|
4915
|
+
if (d - s >= 2)
|
|
4916
|
+
iv.push([s, d]);
|
|
4917
|
+
}
|
|
4918
|
+
iv.sort((a, b) => a[0] - b[0]);
|
|
4919
|
+
const segS = [];
|
|
4920
|
+
const segE = [];
|
|
4921
|
+
for (const [s, d] of iv) {
|
|
4922
|
+
const last = segE.length - 1;
|
|
4923
|
+
if (last >= 0 && s < segE[last])
|
|
4924
|
+
segE[last] = Math.max(segE[last], d);
|
|
4925
|
+
else {
|
|
4926
|
+
segS.push(s);
|
|
4927
|
+
segE.push(d);
|
|
4928
|
+
}
|
|
4929
|
+
}
|
|
4930
|
+
const horizon = (f) => {
|
|
4931
|
+
let a = 0;
|
|
4932
|
+
let b = segS.length;
|
|
4933
|
+
while (a < b) {
|
|
4934
|
+
const mid = (a + b) >>> 1;
|
|
4935
|
+
if (segS[mid] < f)
|
|
4936
|
+
a = mid + 1;
|
|
4937
|
+
else
|
|
4938
|
+
b = mid;
|
|
4939
|
+
}
|
|
4940
|
+
return a > 0 && f < segE[a - 1] ? segS[a - 1] : f;
|
|
4941
|
+
};
|
|
4942
|
+
return { order, hi, from, horizon };
|
|
4943
|
+
});
|
|
4944
|
+
if (prepared.length === 0)
|
|
4945
|
+
return (f) => f;
|
|
4946
|
+
return (f) => {
|
|
4947
|
+
let out = f;
|
|
4948
|
+
for (const p of prepared) {
|
|
4949
|
+
let cur = f;
|
|
4950
|
+
let least = Infinity;
|
|
4951
|
+
for (let k = 0;;) {
|
|
4952
|
+
const fev = p.horizon(cur);
|
|
4953
|
+
while (k < p.order.length && p.hi[p.order[k]] >= fev)
|
|
4954
|
+
least = Math.min(least, p.from[p.order[k++]]);
|
|
4955
|
+
if (least >= cur)
|
|
4956
|
+
break;
|
|
4957
|
+
cur = least;
|
|
4958
|
+
}
|
|
4959
|
+
out = Math.min(out, cur);
|
|
4960
|
+
}
|
|
4961
|
+
return out;
|
|
4962
|
+
};
|
|
4963
|
+
}
|
|
4964
|
+
export function evidenceFrontierForTest(execs, rows, f) {
|
|
4965
|
+
const t = {
|
|
4966
|
+
starts: Int32Array.from(rows, (r) => r[0]),
|
|
4967
|
+
ends: Int32Array.from(rows, (r) => r[1]),
|
|
4968
|
+
family: new Uint8Array(rows.length),
|
|
4969
|
+
anchor: Int32Array.from(rows, (r) => r[0]),
|
|
4970
|
+
closeAt: Int32Array.from(rows, (r) => r[2]),
|
|
4971
|
+
};
|
|
4972
|
+
return createEvidenceFrontier([{ execs: execs.flat(), rows: t, at: (v) => v }])(f);
|
|
4454
4973
|
}
|
|
4455
|
-
function
|
|
4974
|
+
export function forensicExecutionsForTest(text) {
|
|
4975
|
+
const out = [];
|
|
4976
|
+
for (const r of runRedaction(text, false, false, false, "free-text", "multi-line", { kind: "head", emitEnd: text.length }).evidence) {
|
|
4977
|
+
for (let k = 0; k < r.execs.length; k += 3)
|
|
4978
|
+
out.push([r.at(r.execs[k]), r.at(r.execs[k + 1]), r.at(r.execs[k + 2])]);
|
|
4979
|
+
}
|
|
4980
|
+
return out;
|
|
4981
|
+
}
|
|
4982
|
+
export function renderRedactionSpans(text, spans, from, until) {
|
|
4456
4983
|
if (from >= until)
|
|
4457
4984
|
return "";
|
|
4458
4985
|
const parts = [];
|
|
@@ -4471,9 +4998,11 @@ function renderRange(text, spans, from, until) {
|
|
|
4471
4998
|
parts.push(text.slice(at, until));
|
|
4472
4999
|
return parts.join("");
|
|
4473
5000
|
}
|
|
4474
|
-
const
|
|
4475
|
-
const streamRescanStep = (n) => Math.max(STREAM_RESCAN_MIN, n >>> 5);
|
|
5001
|
+
const streamRescanStep = (n) => Math.max(1, n >>> 5);
|
|
4476
5002
|
const STREAM_WINDOW_HORIZON = 2;
|
|
5003
|
+
if (STREAM_WINDOW_HORIZON * MAX_DECISION_REACH > MAX_RECOGNITION_SPAN) {
|
|
5004
|
+
throw new Error(`redact: the horizon of the scan window (${STREAM_WINDOW_HORIZON} × ${MAX_DECISION_REACH} units) exceeds the longest recognition span (${MAX_RECOGNITION_SPAN}) — the exit seat's margin would be shorter than what a decision reads`);
|
|
5005
|
+
}
|
|
4477
5006
|
const STREAM_WINDOW_MIN = 2048;
|
|
4478
5007
|
function deriveStreamWindowAlphabets(priors) {
|
|
4479
5008
|
const blank = new Uint8Array(0x10000);
|
|
@@ -4493,7 +5022,7 @@ function deriveStreamWindowAlphabets(priors) {
|
|
|
4493
5022
|
throw new Error("redact: an anchored arm declares an empty anchor literal");
|
|
4494
5023
|
for (let i = 0; i < anchor.length; i++) {
|
|
4495
5024
|
const c = anchor.charCodeAt(i);
|
|
4496
|
-
if (INVISIBLE_UNIT_CLASS[c] !== 0 || FORMAT_CODEPOINT_TABLE[c] === 1 || (c & 0xf800) === 0xd800 || c === CH_BACKSLASH) {
|
|
5025
|
+
if (INVISIBLE_UNIT_CLASS[c] !== 0 || FORMAT_CODEPOINT_TABLE[c] === 1 || isReadingIgnorable(c) || (c & 0xf800) === 0xd800 || c === CH_BACKSLASH) {
|
|
4497
5026
|
throw new Error(`redact: anchor literal ${JSON.stringify(anchor)} holds a unit some reading deletes or reads as an escape (index ${i}) — its presence is not monotone under deletion, so the stream window's delimiter check on the most-deleted reading would be incomplete`);
|
|
4498
5027
|
}
|
|
4499
5028
|
}
|
|
@@ -4557,15 +5086,70 @@ function windowAdvancePoint(text, units, alphabets = STREAM_WINDOW_ALPHABETS) {
|
|
|
4557
5086
|
return at <= 0 ? 0 : text.lastIndexOf("\n", at - 1) + 1;
|
|
4558
5087
|
}
|
|
4559
5088
|
function windowIndependentAt(text, q) {
|
|
4560
|
-
|
|
5089
|
+
return windowVerdictAt(text, q) === "independent";
|
|
5090
|
+
}
|
|
5091
|
+
function windowVerdictAt(text, q) {
|
|
5092
|
+
const fullRun = runRedaction(text, false, false, false, "free-text", "multi-line", { kind: "head", emitEnd: text.length });
|
|
5093
|
+
const full = fullRun.spans;
|
|
4561
5094
|
if (full.some((s) => s.start < q && s.end > q))
|
|
4562
|
-
return
|
|
5095
|
+
return "span-straddles";
|
|
5096
|
+
if (fullRun.evidence.some((r) => footprintStraddles(r, q)))
|
|
5097
|
+
return "footprint-straddles";
|
|
5098
|
+
if (fullRun.evidence.some((r) => rowStraddles(r, q)))
|
|
5099
|
+
return "row-straddles";
|
|
4563
5100
|
const after = full.filter((s) => s.start >= q);
|
|
4564
5101
|
const tail = text.slice(q);
|
|
4565
|
-
const
|
|
5102
|
+
const aloneRun = runRedaction(tail, false, false, false, "free-text", "multi-line", { kind: "head", emitEnd: tail.length });
|
|
5103
|
+
const alone = aloneRun.spans;
|
|
4566
5104
|
if (after.length !== alone.length)
|
|
5105
|
+
return "spans-differ";
|
|
5106
|
+
if (!after.every((a, i) => a.start - q === alone[i].start && a.end - q === alone[i].end && a.repl === alone[i].repl))
|
|
5107
|
+
return "spans-differ";
|
|
5108
|
+
if (!sameRowSet(rowKeysFrom(fullRun.evidence, q), rowKeysFrom(aloneRun.evidence, 0)))
|
|
5109
|
+
return "rows-differ";
|
|
5110
|
+
return fullRun.view < q ? "view-straddles" : "independent";
|
|
5111
|
+
}
|
|
5112
|
+
export function windowVerdictAtForTest(text, q) {
|
|
5113
|
+
return windowVerdictAt(text, q);
|
|
5114
|
+
}
|
|
5115
|
+
function footprintStraddles(r, q) {
|
|
5116
|
+
for (let k = 0; k < r.execs.length; k += 3)
|
|
5117
|
+
if (r.at(r.execs[k]) < q && r.at(r.execs[k + 1]) >= q)
|
|
5118
|
+
return true;
|
|
5119
|
+
return false;
|
|
5120
|
+
}
|
|
5121
|
+
function rowStraddles(r, q) {
|
|
5122
|
+
const t = r.rows;
|
|
5123
|
+
for (let k = 0; k < t.starts.length; k++) {
|
|
5124
|
+
if (r.at(t.starts[k]) >= q)
|
|
5125
|
+
continue;
|
|
5126
|
+
const c = t.closeAt[k];
|
|
5127
|
+
if (Math.max(r.at(t.ends[k] - 1) + 1, c >= 0 ? r.at(c) + 1 : 0) > q)
|
|
5128
|
+
return true;
|
|
5129
|
+
}
|
|
5130
|
+
return false;
|
|
5131
|
+
}
|
|
5132
|
+
function rowKeysFrom(readings, q) {
|
|
5133
|
+
const keys = new Set();
|
|
5134
|
+
for (const r of readings) {
|
|
5135
|
+
const t = r.rows;
|
|
5136
|
+
for (let k = 0; k < t.starts.length; k++) {
|
|
5137
|
+
const s = r.at(t.starts[k]);
|
|
5138
|
+
if (s < q)
|
|
5139
|
+
continue;
|
|
5140
|
+
const c = t.closeAt[k];
|
|
5141
|
+
keys.add(`${s - q},${r.at(t.ends[k] - 1) + 1 - q},${t.family[k]},${r.at(t.anchor[k]) - q},${c >= 0 ? r.at(c) - q : -1}`);
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
return keys;
|
|
5145
|
+
}
|
|
5146
|
+
function sameRowSet(a, b) {
|
|
5147
|
+
if (a.size !== b.size)
|
|
4567
5148
|
return false;
|
|
4568
|
-
|
|
5149
|
+
for (const k of a)
|
|
5150
|
+
if (!b.has(k))
|
|
5151
|
+
return false;
|
|
5152
|
+
return true;
|
|
4569
5153
|
}
|
|
4570
5154
|
export function windowAdvancePointForTest(text, units, extra = []) {
|
|
4571
5155
|
return windowAdvancePoint(text, units, extra.length === 0 ? STREAM_WINDOW_ALPHABETS : deriveStreamWindowAlphabets([...armPool.priors, ...extra]));
|
|
@@ -4574,18 +5158,53 @@ export function windowIndependentAtForTest(text, q) {
|
|
|
4574
5158
|
return windowIndependentAt(text, q);
|
|
4575
5159
|
}
|
|
4576
5160
|
export function createRedactionStream() {
|
|
4577
|
-
return openRedactionStream(
|
|
5161
|
+
return openRedactionStream();
|
|
4578
5162
|
}
|
|
4579
5163
|
export function createRedactionStreamWithoutWindowForTest() {
|
|
4580
|
-
return openRedactionStream(
|
|
5164
|
+
return openRedactionStream(false);
|
|
4581
5165
|
}
|
|
4582
5166
|
export function createRedactionStreamWithCertifierForTest(certify) {
|
|
4583
|
-
return openRedactionStream(
|
|
4584
|
-
}
|
|
4585
|
-
export function
|
|
4586
|
-
return openRedactionStream(
|
|
4587
|
-
}
|
|
4588
|
-
function
|
|
5167
|
+
return openRedactionStream(true, certify);
|
|
5168
|
+
}
|
|
5169
|
+
export function createRedactionStreamWithFrontierForTest(adjust) {
|
|
5170
|
+
return openRedactionStream(true, windowIndependentAt, adjust);
|
|
5171
|
+
}
|
|
5172
|
+
function settledCut(win, joints = NO_JOINTS) {
|
|
5173
|
+
const n = win.length;
|
|
5174
|
+
let rounds = 1;
|
|
5175
|
+
let r = runRedaction(win, false, false, false, "free-text", "multi-line", { kind: "head", emitEnd: n }, 0, joints);
|
|
5176
|
+
const lattice = r.lattice;
|
|
5177
|
+
const token = tokenTailOpen(win);
|
|
5178
|
+
let scanned = n;
|
|
5179
|
+
for (let tail = Math.min(lattice, token), back = 1; tail < scanned; back *= 2) {
|
|
5180
|
+
scanned = Math.max(0, Math.min(tail, scanned - back));
|
|
5181
|
+
const head = win.slice(0, scanned);
|
|
5182
|
+
r = runRedaction(head, false, false, false, "free-text", "multi-line", { kind: "head", emitEnd: scanned }, 0, joints);
|
|
5183
|
+
rounds += 1;
|
|
5184
|
+
tail = Math.min(r.lattice, tokenTailOpen(head));
|
|
5185
|
+
}
|
|
5186
|
+
const spans = r.spans;
|
|
5187
|
+
const inputs = { n, view: r.view, lattice, token, evidence: createEvidenceFrontier(r.evidence) };
|
|
5188
|
+
const frontier = settledFrontier(inputs);
|
|
5189
|
+
let cut = frontier;
|
|
5190
|
+
for (const s of spans)
|
|
5191
|
+
if (s.start < cut && (s.end >= cut || s.end >= scanned))
|
|
5192
|
+
cut = s.start;
|
|
5193
|
+
return { cut, spans, inputs, frontier, rounds };
|
|
5194
|
+
}
|
|
5195
|
+
export function settledCutsForTest(text) {
|
|
5196
|
+
const s = settledCut(text);
|
|
5197
|
+
const terms = Object.fromEntries(READ_PORTS.map((k) => [k, FRONTIER_TERMS[k](s.inputs, s.frontier)]));
|
|
5198
|
+
return { cut: s.cut, settled: renderRedactionSpans(text, s.spans, 0, s.cut), frontier: s.frontier, terms, rounds: s.rounds };
|
|
5199
|
+
}
|
|
5200
|
+
export function createScanViewForTest(text) {
|
|
5201
|
+
const r = new ScanReader(text);
|
|
5202
|
+
return { view: r, open: () => r.open, unattributed: () => r.unattributed };
|
|
5203
|
+
}
|
|
5204
|
+
export function expandHeadUnitsForTest(src, flags = "g") {
|
|
5205
|
+
return expandHeadUnits(src, flags).length;
|
|
5206
|
+
}
|
|
5207
|
+
function openRedactionStream(windowed = true, certify = windowIndependentAt, adjust = 0) {
|
|
4589
5208
|
let past = [];
|
|
4590
5209
|
let total = 0;
|
|
4591
5210
|
let win = "";
|
|
@@ -4596,6 +5215,8 @@ function openRedactionStream(pendingTail, windowed = true, certify = windowIndep
|
|
|
4596
5215
|
let sent = "";
|
|
4597
5216
|
let scannedAt = 0;
|
|
4598
5217
|
let evaluatedAt = -1;
|
|
5218
|
+
const commits = [];
|
|
5219
|
+
const jointsInWindow = () => (commits.length === 0 ? NO_JOINTS : commits.filter((c) => c > base).map((c) => c - base));
|
|
4599
5220
|
let retryAt = 0;
|
|
4600
5221
|
const whole = () => (past.length === 0 ? win : past.join("") + win);
|
|
4601
5222
|
const advanceWindow = () => {
|
|
@@ -4604,7 +5225,7 @@ function openRedactionStream(pendingTail, windowed = true, certify = windowIndep
|
|
|
4604
5225
|
evaluatedAt = total;
|
|
4605
5226
|
retryAt = win.length + (win.length >> 1);
|
|
4606
5227
|
windowEvaluations += 1;
|
|
4607
|
-
const q = windowAdvancePoint(win, STREAM_WINDOW_HORIZON *
|
|
5228
|
+
const q = windowAdvancePoint(win, STREAM_WINDOW_HORIZON * MAX_DECISION_REACH);
|
|
4608
5229
|
if (q < 0) {
|
|
4609
5230
|
retryAt = 0;
|
|
4610
5231
|
return;
|
|
@@ -4627,25 +5248,18 @@ function openRedactionStream(pendingTail, windowed = true, certify = windowIndep
|
|
|
4627
5248
|
total += chunk.length;
|
|
4628
5249
|
},
|
|
4629
5250
|
takeSettled() {
|
|
4630
|
-
if (total -
|
|
4631
|
-
return "";
|
|
4632
|
-
if (total - scannedAt < streamRescanStep(total))
|
|
5251
|
+
if (released === total || total - scannedAt < streamRescanStep(total))
|
|
4633
5252
|
return "";
|
|
4634
5253
|
scannedAt = total;
|
|
4635
|
-
const emitEnd = pendingTailStart(win, pendingTail);
|
|
4636
5254
|
const from = released - base;
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
let cut = emitEnd;
|
|
4641
|
-
for (const s of spans)
|
|
4642
|
-
if (s.start < cut && s.end > cut)
|
|
4643
|
-
cut = s.start;
|
|
5255
|
+
const settled = settledCut(win, jointsInWindow());
|
|
5256
|
+
const spans = settled.spans;
|
|
5257
|
+
let cut = Math.min(win.length, settled.cut + adjust);
|
|
4644
5258
|
if (cut > 0 && cut < win.length && (win.charCodeAt(cut - 1) & 0xfc00) === 0xd800 && (win.charCodeAt(cut) & 0xfc00) === 0xdc00)
|
|
4645
5259
|
cut -= 1;
|
|
4646
5260
|
if (cut <= from)
|
|
4647
5261
|
return "";
|
|
4648
|
-
const out =
|
|
5262
|
+
const out = renderRedactionSpans(win, spans, from, cut);
|
|
4649
5263
|
released = base + cut;
|
|
4650
5264
|
sent += out;
|
|
4651
5265
|
return out;
|
|
@@ -4653,9 +5267,10 @@ function openRedactionStream(pendingTail, windowed = true, certify = windowIndep
|
|
|
4653
5267
|
takeAll() {
|
|
4654
5268
|
if (released === total)
|
|
4655
5269
|
return "";
|
|
4656
|
-
const spans = runRedaction(win, false, false, false, "free-text", "multi-line", WHOLE_EXTENT).spans;
|
|
4657
|
-
const out =
|
|
5270
|
+
const spans = runRedaction(win, false, false, false, "free-text", "multi-line", WHOLE_EXTENT, 0, jointsInWindow()).spans;
|
|
5271
|
+
const out = renderRedactionSpans(win, spans, released - base, win.length);
|
|
4658
5272
|
released = scannedAt = total;
|
|
5273
|
+
commits.push(total);
|
|
4659
5274
|
sent += out;
|
|
4660
5275
|
return out;
|
|
4661
5276
|
},
|
|
@@ -4663,12 +5278,13 @@ function openRedactionStream(pendingTail, windowed = true, certify = windowIndep
|
|
|
4663
5278
|
if (deliveredFrom === total)
|
|
4664
5279
|
return { rest: "", diverged: false };
|
|
4665
5280
|
const buf = whole();
|
|
4666
|
-
const spans = runRedaction(buf, false, false, false, "free-text", "multi-line", WHOLE_EXTENT)
|
|
4667
|
-
const split = released > deliveredFrom && spans.some((s) => s.start < released && s.end > released);
|
|
4668
|
-
return { rest:
|
|
5281
|
+
const { spans, crossed } = runRedaction(buf, false, false, false, "free-text", "multi-line", WHOLE_EXTENT, 0, commits);
|
|
5282
|
+
const split = released > deliveredFrom && (spans.some((s) => s.start < released && s.end > released) || crossed.some((j) => j > deliveredFrom));
|
|
5283
|
+
return { rest: renderRedactionSpans(buf, spans, released, buf.length), diverged: split || renderRedactionSpans(buf, spans, deliveredFrom, released) !== sent };
|
|
4669
5284
|
},
|
|
4670
5285
|
skip() {
|
|
4671
5286
|
released = deliveredFrom = scannedAt = total;
|
|
5287
|
+
commits.push(total);
|
|
4672
5288
|
sent = "";
|
|
4673
5289
|
},
|
|
4674
5290
|
endBlock() {
|
|
@@ -4836,10 +5452,6 @@ function shapeLawCredentialInQueryOrFragment(canonical) {
|
|
|
4836
5452
|
}
|
|
4837
5453
|
return false;
|
|
4838
5454
|
}
|
|
4839
|
-
let displaySafeFailClosedWarned = false;
|
|
4840
|
-
export function resetDisplaySafeFailClosedWarnForTest() {
|
|
4841
|
-
displaySafeFailClosedWarned = false;
|
|
4842
|
-
}
|
|
4843
5455
|
export function buildDisplaySafeUrl(raw, positionalLaw = displayUrlOf) {
|
|
4844
5456
|
return buildDisplaySafeUrlChecked(raw, positionalLaw).text;
|
|
4845
5457
|
}
|
|
@@ -4875,10 +5487,6 @@ export function buildDisplaySafeRefusal(text, sourceUrls) {
|
|
|
4875
5487
|
const REFUSAL_WITHHELD_TEXT = "[route refusal text withheld: it quotes a configured URL that carries a credential, and the upstream wording cannot be re-redacted safely once the URL has been rewritten for display. " +
|
|
4876
5488
|
"The machine-readable verdict is on the pairing field beside this one; fix the configuration so the credential is not in the URL.]";
|
|
4877
5489
|
function noteDisplaySafeFailClosed(level) {
|
|
4878
|
-
|
|
4879
|
-
return;
|
|
4880
|
-
displaySafeFailClosedWarned = true;
|
|
4881
|
-
process.emitWarning(`display-safe URL composition fell back to fail-closed (${level}): a part of the configured URL was judged to carry a credential that the composition cannot redact at byte granularity, so that whole part is withheld. ` +
|
|
4882
|
-
`The product is safe, but this deployment has an input hitting the composition seam — report it upstream. No original bytes are logged.`, "SemaRedactionFailClosed");
|
|
5490
|
+
recordFailOpen("server.redact.display-safe-fail-closed", `level=${level}`);
|
|
4883
5491
|
}
|
|
4884
5492
|
//# sourceMappingURL=redact.js.map
|