hippo-memory 1.71.0 → 2.0.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/README.md +7 -5
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +11 -26
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +3 -2
- package/dist/api/audit.d.ts +30 -2
- package/dist/api/audit.js +48 -7
- package/dist/api/auth.d.ts +11 -9
- package/dist/api/auth.js +39 -40
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-auto.js +4 -2
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +15 -29
- package/dist/api/context.js +29 -18
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +3 -2
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +7 -3
- package/dist/api/forget.js +24 -14
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/graph.js +2 -1
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +5 -1
- package/dist/api/learn.js +71 -44
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +21 -1
- package/dist/api/memories.js +51 -1
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +17 -16
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +8 -1
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +26 -28
- package/dist/api/prompt-hook.d.ts +17 -2
- package/dist/api/prompt-hook.js +45 -4
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +10 -5
- package/dist/api/recall-pipeline.js +23 -24
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +51 -73
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +15 -7
- package/dist/api/remember.d.ts +7 -3
- package/dist/api/remember.js +19 -16
- package/dist/api/session-end.d.ts +46 -0
- package/dist/api/session-end.js +131 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +16 -11
- package/dist/api/sleep.js +4 -3
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +3 -7
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +7 -7
- package/dist/capture/compaction-spool.js +60 -51
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +3 -2
- package/dist/capture/session-worker.js +22 -10
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +20 -20
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +16 -17
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +6 -2
- package/dist/cli/client.js +37 -21
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +13 -13
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +2 -2
- package/dist/cli/curate.js +32 -36
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +7 -285
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +6 -6
- package/dist/cli/hook-runtime.js +9 -36
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +174 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +18 -17
- package/dist/cli/remember.js +17 -17
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +11 -6
- package/dist/cli/session-hooks.d.ts +1 -5
- package/dist/cli/session-hooks.js +89 -168
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +3 -3
- package/dist/cli/transfer.js +64 -43
- package/dist/cli/usage.d.ts +1 -80
- package/dist/cli/usage.js +2 -696
- package/dist/cli/verb-row.d.ts +34 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +234 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +236 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +257 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +314 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +24 -315
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +39 -4
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +5 -29
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +35 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +29 -0
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +4 -28
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +2 -2
- package/dist/consolidate/dag.js +29 -18
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +6 -4
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +3 -2
- package/dist/consolidate/merge.js +8 -8
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +9 -6
- package/dist/consolidate/traces.js +5 -5
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +22 -18
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +4 -4
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +14 -8
- package/dist/core/memory.js +35 -23
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +23 -18
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +12 -2
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +2 -2
- package/dist/db/connect.js +7 -7
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.d.ts +0 -4
- package/dist/db/physics-state.js +7 -33
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +19 -5
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +18 -15
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +19 -25
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +12 -5
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +10 -4
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +4 -4
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +25 -23
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/learn/autolearn.d.ts +15 -3
- package/dist/learn/autolearn.js +38 -16
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +7 -5
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +18 -9
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.d.ts +1 -1
- package/dist/mcp/memory-tools.js +8 -9
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +22 -20
- package/dist/mcp/stdio.js +37 -16
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +71 -98
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +12 -0
- package/dist/search/embed-memories.js +389 -0
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +14 -17
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.js +24 -15
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +34 -84
- package/dist/server/client-ip.d.ts +9 -6
- package/dist/server/client-ip.js +36 -17
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -133
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +19 -40
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +29 -12
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +4 -40
- package/dist/server.js +3 -29
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +8 -13
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +10 -3
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +39 -38
- package/dist/store/ambient.js +7 -7
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +59 -30
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +6 -5
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +418 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +13 -9
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +33 -0
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +35 -60
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +24 -57
- package/dist/store/dashboard-reads.js +8 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +40 -6
- package/dist/store/delivery-recorder.d.ts +12 -5
- package/dist/store/delivery-recorder.js +13 -11
- package/dist/store/descendant-page.js +8 -4
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +10 -4
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +35 -4
- package/dist/store/entry-reads.js +86 -19
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +15 -12
- package/dist/store/entry-writes.js +54 -22
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +22 -19
- package/dist/store/graph-reads.js +9 -6
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +10 -4
- package/dist/store/handoffs.js +10 -9
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +19 -10
- package/dist/store/open.d.ts +2 -5
- package/dist/store/open.js +42 -54
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +68 -6
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quality-repair.js +1 -1
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +20 -3
- package/dist/store/rejected-values.js +16 -10
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +11 -0
- package/dist/store/rule-sql.js +31 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +18 -16
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +6 -4
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +3 -3
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +11 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +15 -7
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -22
- package/dist/store/summaries.d.ts +10 -3
- package/dist/store/summaries.js +54 -11
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +8 -4
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +6 -1
- package/dist/util/anthropic-messages.js +26 -7
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +12 -2
- package/dist/util/env.js +12 -2
- package/dist/util/format.d.ts +5 -0
- package/dist/util/format.js +10 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +9 -3
- package/dist/util/request-scope.js +18 -9
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -2
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { handleGitHubEventsWebhook } from '../connectors/github/webhook.js';
|
|
2
|
+
import { handleSlackEventsWebhook } from '../connectors/slack/webhook.js';
|
|
1
3
|
import { withSqliteOffLoop } from '../db/index.js';
|
|
2
|
-
import { hasGroup } from '../store/index.js';
|
|
4
|
+
import { hasGroup, requireGroup } from '../store/index.js';
|
|
3
5
|
import { runsOffLoop } from '../store/sqlite/worker-store.js';
|
|
4
6
|
import { HttpError, JSON_HEADERS, sendJson, STORE_NOT_PORTED_MESSAGE } from '../util/http-util.js';
|
|
5
|
-
import { buildContextWithAuth,
|
|
7
|
+
import { assertCrossTenantAdmin, buildContextWithAuth, isLoopback } from './auth.js';
|
|
6
8
|
import { matchPath, noteAccess } from './request.js';
|
|
7
9
|
import { handleApproveQuarantine, handleCreateAuthKey, handleListAudit, handleListAuthKeys, handleListQuarantine, handleRejectQuarantine, handleRevokeAuthKey } from './routes/admin.js';
|
|
8
10
|
import { handleCloseCustomerNote, handleCreateCustomerNote, handleGetCustomerNote, handleListCustomerNotes, handleSupersedeCustomerNote } from './routes/customer-notes.js';
|
|
@@ -16,94 +18,134 @@ import { handleCloseProjectBrief, handleCreateProjectBrief, handleGetProjectBrie
|
|
|
16
18
|
import { handleAssembleSession, handleDrillRecall, handleGetContext, handleRecallMemories } from './routes/recall.js';
|
|
17
19
|
import { handleCloseSkill, handleCreateSkill, handleExportSkills, handleGetSkill, handleListSkills, handleSupersedeSkill } from './routes/skills.js';
|
|
18
20
|
import { parseJsonBody } from './validation.js';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
const WEBHOOK_GROUPS = ['entryWrites', 'connectorWrites', 'connectorEvents'];
|
|
22
|
+
/** A store missing a group a delivery writes through refuses the webhook up front, so no delivery is acknowledged and then half stored. */
|
|
23
|
+
function webhook(handle) {
|
|
24
|
+
return async ({ req, res, opts }) => {
|
|
25
|
+
for (const group of WEBHOOK_GROUPS)
|
|
26
|
+
requireGroup(opts.store, group);
|
|
27
|
+
await handle({ req, res, opts }, opts.store);
|
|
28
|
+
};
|
|
27
29
|
}
|
|
28
|
-
/** The /v1 routes in dispatch order; the first entry whose method and path match handles the request.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{ method: '
|
|
32
|
-
{ method: 'GET', path: '/v1/
|
|
33
|
-
{ method: 'GET',
|
|
34
|
-
{ method: 'GET', pattern: '/v1/
|
|
35
|
-
{ method: '
|
|
36
|
-
{ method: 'POST', pattern: '/v1/memories/:id/
|
|
37
|
-
{ method: 'POST', pattern: '/v1/memories/:id/
|
|
38
|
-
{ method: '
|
|
39
|
-
|
|
40
|
-
{ method: '
|
|
41
|
-
{ method: 'POST', path: '/v1/
|
|
42
|
-
{ method: '
|
|
43
|
-
{ method: '
|
|
44
|
-
|
|
45
|
-
{ method: '
|
|
46
|
-
{ method: '
|
|
47
|
-
{ method: '
|
|
48
|
-
{ method: 'GET', path: '/v1/
|
|
49
|
-
{ method: 'POST',
|
|
50
|
-
{ method: '
|
|
51
|
-
{ method: 'GET', path: '/v1/
|
|
52
|
-
{ method: '
|
|
53
|
-
{ method: '
|
|
54
|
-
{ method: '
|
|
55
|
-
{ method: 'GET',
|
|
56
|
-
{ method: 'POST', regex: /^\/v1\/
|
|
57
|
-
{ method: 'POST',
|
|
58
|
-
{ method: 'GET',
|
|
59
|
-
{ method: 'POST',
|
|
60
|
-
{ method: '
|
|
61
|
-
{ method: '
|
|
62
|
-
{ method: 'POST',
|
|
63
|
-
{ method: 'GET',
|
|
64
|
-
{ method: 'POST',
|
|
65
|
-
{ method: '
|
|
66
|
-
{ method: '
|
|
67
|
-
{ method: 'POST',
|
|
68
|
-
{ method: 'GET',
|
|
69
|
-
{ method: 'POST',
|
|
70
|
-
{ method: '
|
|
71
|
-
{ method: 'GET',
|
|
72
|
-
{ method: 'POST',
|
|
73
|
-
{ method: '
|
|
74
|
-
{ method: 'GET',
|
|
75
|
-
{ method: 'POST',
|
|
76
|
-
{ method: '
|
|
77
|
-
{ method: 'GET',
|
|
78
|
-
{ method: 'POST',
|
|
79
|
-
{ method: '
|
|
80
|
-
{ method: 'GET',
|
|
81
|
-
{ method: 'POST',
|
|
82
|
-
{ method: '
|
|
83
|
-
{ method: '
|
|
84
|
-
{ method: 'POST',
|
|
85
|
-
{ method: '
|
|
86
|
-
{ method: '
|
|
87
|
-
{ method: 'POST',
|
|
88
|
-
|
|
89
|
-
{ method: 'POST', regex: /^\/v1\/
|
|
90
|
-
{ method: '
|
|
91
|
-
{ method: '
|
|
30
|
+
/** The /v1 routes in dispatch order; the first entry whose method and path match handles the request. Each row's `auth` is what the
|
|
31
|
+
* dispatch gate proves before its handler runs, so a handler never checks the caller itself. */
|
|
32
|
+
export const V1_ROUTES = [
|
|
33
|
+
{ method: 'POST', path: '/v1/memories', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleCreateMemory },
|
|
34
|
+
{ method: 'GET', path: '/v1/graph', auth: 'caller', storeReady: 'graphReads', loop: 'off', handler: handleGetGraph },
|
|
35
|
+
{ method: 'GET', path: '/v1/memories', auth: 'caller', storeReady: 'base', loop: 'off', handler: handleRecallMemories },
|
|
36
|
+
{ method: 'GET', pattern: '/v1/sessions/:id/assemble', auth: 'caller', storeReady: 'dagReads', loop: 'off', handler: handleAssembleSession },
|
|
37
|
+
{ method: 'GET', pattern: '/v1/recall/drill/:id', auth: 'caller', storeReady: 'dagReads', handler: handleDrillRecall },
|
|
38
|
+
{ method: 'POST', pattern: '/v1/memories/:id/archive', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleArchiveMemory },
|
|
39
|
+
{ method: 'POST', pattern: '/v1/memories/:id/supersede', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleSupersedeMemory },
|
|
40
|
+
{ method: 'POST', pattern: '/v1/memories/:id/promote', auth: 'caller', sqliteOnly: 'copies a memory between the two local hippo.db files',
|
|
41
|
+
handler: handlePromoteMemory },
|
|
42
|
+
{ method: 'DELETE', pattern: '/v1/memories/:id', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleForgetMemory },
|
|
43
|
+
{ method: 'POST', path: '/v1/outcome', auth: 'caller', storeReady: 'entryWrites', handler: handleApplyOutcome },
|
|
44
|
+
{ method: 'GET', path: '/v1/context', auth: 'caller', storeReady: 'contextReads', handler: handleGetContext },
|
|
45
|
+
{ method: 'POST', path: '/v1/sleep', auth: 'host-admin-local', sqliteOnly: 'consolidates every tenant under the local hippo root in this process',
|
|
46
|
+
handler: handleSleep },
|
|
47
|
+
{ method: 'POST', path: '/v1/auth/keys', auth: 'caller', storeReady: 'keyWrites', loop: 'off', handler: handleCreateAuthKey },
|
|
48
|
+
{ method: 'GET', path: '/v1/auth/keys', auth: 'caller', storeReady: 'keyWrites', loop: 'off', handler: handleListAuthKeys },
|
|
49
|
+
{ method: 'DELETE', pattern: '/v1/auth/keys/:keyId', auth: 'caller', storeReady: 'keyAudit', loop: 'off', handler: handleRevokeAuthKey },
|
|
50
|
+
{ method: 'GET', path: '/v1/quarantine', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleListQuarantine },
|
|
51
|
+
{ method: 'POST', pattern: '/v1/quarantine/:id/approve', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleApproveQuarantine },
|
|
52
|
+
{ method: 'POST', pattern: '/v1/quarantine/:id/reject', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleRejectQuarantine },
|
|
53
|
+
{ method: 'GET', path: '/v1/audit', auth: 'admin', storeReady: 'auditLog', loop: 'off', handler: handleListAudit },
|
|
54
|
+
{ method: 'POST', path: '/v1/predictions', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleCreatePrediction },
|
|
55
|
+
{ method: 'GET', path: '/v1/predictions', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleListPredictions },
|
|
56
|
+
{ method: 'GET', path: '/v1/predictions/stats', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handlePredictionStats },
|
|
57
|
+
{ method: 'GET', regex: /^\/v1\/predictions\/(\d+)$/, auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleGetPrediction },
|
|
58
|
+
{ method: 'POST', regex: /^\/v1\/predictions\/(\d+)\/close$/, auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleClosePrediction },
|
|
59
|
+
{ method: 'POST', path: '/v1/decisions', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateDecision },
|
|
60
|
+
{ method: 'GET', path: '/v1/decisions', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListDecisions },
|
|
61
|
+
{ method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeDecision },
|
|
62
|
+
{ method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseDecision },
|
|
63
|
+
{ method: 'GET', regex: /^\/v1\/decisions\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetDecision },
|
|
64
|
+
{ method: 'POST', path: '/v1/incidents', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateIncident },
|
|
65
|
+
{ method: 'GET', path: '/v1/incidents', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListIncidents },
|
|
66
|
+
{ method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/resolve$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleResolveIncident },
|
|
67
|
+
{ method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseIncident },
|
|
68
|
+
{ method: 'GET', regex: /^\/v1\/incidents\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetIncident },
|
|
69
|
+
{ method: 'POST', path: '/v1/processes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateProcess },
|
|
70
|
+
{ method: 'GET', path: '/v1/processes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListProcesses },
|
|
71
|
+
{ method: 'POST', regex: /^\/v1\/processes\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeProcess },
|
|
72
|
+
{ method: 'POST', regex: /^\/v1\/processes\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseProcess },
|
|
73
|
+
{ method: 'GET', regex: /^\/v1\/processes\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetProcess },
|
|
74
|
+
{ method: 'POST', path: '/v1/policies', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreatePolicy },
|
|
75
|
+
{ method: 'GET', path: '/v1/policies', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListPolicies },
|
|
76
|
+
{ method: 'GET', path: '/v1/policies/asof', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handlePoliciesAsOf },
|
|
77
|
+
{ method: 'POST', regex: /^\/v1\/policies\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedePolicy },
|
|
78
|
+
{ method: 'POST', regex: /^\/v1\/policies\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleClosePolicy },
|
|
79
|
+
{ method: 'GET', regex: /^\/v1\/policies\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetPolicy },
|
|
80
|
+
{ method: 'POST', path: '/v1/skills', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateSkill },
|
|
81
|
+
{ method: 'GET', path: '/v1/skills', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListSkills },
|
|
82
|
+
{ method: 'GET', path: '/v1/skills/export', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleExportSkills },
|
|
83
|
+
{ method: 'POST', regex: /^\/v1\/skills\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeSkill },
|
|
84
|
+
{ method: 'POST', regex: /^\/v1\/skills\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseSkill },
|
|
85
|
+
{ method: 'GET', regex: /^\/v1\/skills\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetSkill },
|
|
86
|
+
{ method: 'POST', path: '/v1/project-briefs', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateProjectBrief },
|
|
87
|
+
{ method: 'GET', path: '/v1/project-briefs', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListProjectBriefs },
|
|
88
|
+
{ method: 'POST', path: '/v1/project-briefs/refresh', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleRefreshProjectBrief },
|
|
89
|
+
{ method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off',
|
|
90
|
+
handler: handleSupersedeProjectBrief },
|
|
91
|
+
{ method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseProjectBrief },
|
|
92
|
+
{ method: 'GET', regex: /^\/v1\/project-briefs\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetProjectBrief },
|
|
93
|
+
{ method: 'POST', path: '/v1/customer-notes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateCustomerNote },
|
|
94
|
+
{ method: 'GET', path: '/v1/customer-notes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListCustomerNotes },
|
|
95
|
+
{ method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off',
|
|
96
|
+
handler: handleSupersedeCustomerNote },
|
|
97
|
+
{ method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseCustomerNote },
|
|
98
|
+
{ method: 'GET', regex: /^\/v1\/customer-notes\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetCustomerNote },
|
|
99
|
+
{ method: 'POST', path: '/v1/connectors/slack/events', auth: 'webhook-signature', storeReady: 'connectorEvents', handler: webhook(handleSlackEventsWebhook) },
|
|
100
|
+
{ method: 'POST', path: '/v1/connectors/github/events', auth: 'webhook-signature', storeReady: 'connectorEvents',
|
|
101
|
+
handler: webhook(handleGitHubEventsWebhook) },
|
|
92
102
|
];
|
|
93
|
-
/** The
|
|
94
|
-
|
|
95
|
-
function routeMatches(route, method, path) {
|
|
103
|
+
/** The handler bound to this path's params, or null when the path differs. */
|
|
104
|
+
function bindPath(route, path) {
|
|
96
105
|
if ('path' in route)
|
|
97
|
-
return
|
|
106
|
+
return path === route.path ? route.handler : null;
|
|
98
107
|
if ('pattern' in route) {
|
|
99
108
|
const params = matchPath(route.pattern, path);
|
|
100
|
-
return
|
|
109
|
+
return params ? (r) => route.handler(r, params) : null;
|
|
101
110
|
}
|
|
102
111
|
const match = path.match(route.regex);
|
|
103
|
-
return
|
|
112
|
+
return match ? (r) => route.handler(r, match) : null;
|
|
113
|
+
}
|
|
114
|
+
/** The route's run for this request, gate first, or null when method or path differ. The matcher runs before the method check,
|
|
115
|
+
* as the inline route blocks did, so a malformed `%` escape still throws from matchPath on any method. */
|
|
116
|
+
export function routeMatches(route, method, path) {
|
|
117
|
+
if (route.auth === 'webhook-signature') {
|
|
118
|
+
const run = bindPath(route, path);
|
|
119
|
+
if (run === null || method !== route.method)
|
|
120
|
+
return null;
|
|
121
|
+
return async (r) => {
|
|
122
|
+
assertRoutePorted(r.opts, route.storeReady);
|
|
123
|
+
await run(r);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const run = bindPath(route, path);
|
|
127
|
+
if (run === null || method !== route.method)
|
|
128
|
+
return null;
|
|
129
|
+
return async (r) => run({ ...r, ctx: await passAuthGate(route, r) });
|
|
130
|
+
}
|
|
131
|
+
/** The one caller check a gated route passes: sleep refuses a caller off this host before any key work, then one charged auth,
|
|
132
|
+
* then 501 for an unported route, so a bad key is still a 401 there, and the row's role last. */
|
|
133
|
+
async function passAuthGate(route, { req, opts }) {
|
|
134
|
+
const label = routeLabel(route);
|
|
135
|
+
// Defence in depth, not the boundary: a socket address says where a request came from, never who sent it.
|
|
136
|
+
if (route.auth === 'host-admin-local' && !isLoopback(req.socket.remoteAddress)) {
|
|
137
|
+
throw new HttpError(403, `${label} is loopback-only (host-wide consolidation; see CHANGELOG v1.11.4)`);
|
|
138
|
+
}
|
|
139
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
140
|
+
assertRoutePorted(opts, route.storeReady);
|
|
141
|
+
if (route.auth === 'admin' && ctx.actor.role !== 'admin')
|
|
142
|
+
throw new HttpError(403, `${label} requires admin role`);
|
|
143
|
+
if (route.auth === 'host-admin-local')
|
|
144
|
+
assertCrossTenantAdmin(ctx, label);
|
|
145
|
+
return ctx;
|
|
104
146
|
}
|
|
105
147
|
/** The route as the access line names it; a regex route reads as its pattern would, so no line carries a caller's id. */
|
|
106
|
-
function routeLabel(route) {
|
|
148
|
+
export function routeLabel(route) {
|
|
107
149
|
if ('path' in route)
|
|
108
150
|
return route.path;
|
|
109
151
|
if ('pattern' in route)
|
|
@@ -117,61 +159,20 @@ export async function dispatchV1Route(r, method, path) {
|
|
|
117
159
|
if (run === null)
|
|
118
160
|
continue;
|
|
119
161
|
noteAccess(r.req, { route: routeLabel(route) });
|
|
120
|
-
await refuseUnportedRoute(r.req, r.opts, route.storeReady);
|
|
121
162
|
// Only a store with worker threads has moved the route's SQLite work; under any other the handler still opens hippo.db itself.
|
|
122
163
|
await (route.loop === 'off' && runsOffLoop(r.opts.store) ? withSqliteOffLoop(() => run(r)) : run(r));
|
|
123
164
|
return true;
|
|
124
165
|
}
|
|
125
166
|
return false;
|
|
126
167
|
}
|
|
127
|
-
const PLAIN_SEGMENT_RE = /^[A-Za-z0-9._~-]+$/;
|
|
128
|
-
function isPlainV1Path(path) {
|
|
129
|
-
return path.startsWith('/v1/') && new URL(path, 'http://h').pathname === path
|
|
130
|
-
&& path.slice('/v1/'.length).split('/').every((segment) => PLAIN_SEGMENT_RE.test(segment));
|
|
131
|
-
}
|
|
132
|
-
// A plain path never holds a `%`, so matchPath cannot throw here.
|
|
133
|
-
function isCorePath(method, path) {
|
|
134
|
-
return PUBLIC_ROUTES.has(`${method} ${path}`) || V1_ROUTES.some((route) => routeMatches(route, method, path) !== null);
|
|
135
|
-
}
|
|
136
|
-
/** Boot-time check: an add-on path must be plain, unique and not one core serves, so no add-on shadows a core route or hides from dispatch. */
|
|
137
|
-
export function assertAddonRoutes(routes) {
|
|
138
|
-
const seen = new Set();
|
|
139
|
-
for (const { path } of routes) {
|
|
140
|
-
if (!isPlainV1Path(path))
|
|
141
|
-
throw new Error(`add-on route '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
|
|
142
|
-
if (seen.has(path))
|
|
143
|
-
throw new Error(`add-on route '${path}' is registered twice`);
|
|
144
|
-
if (isCorePath('POST', path))
|
|
145
|
-
throw new Error(`add-on route '${path}' is already served by core`);
|
|
146
|
-
seen.add(path);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const PUBLIC_JSON_MAX_BYTES = 64 * 1024;
|
|
150
|
-
/** Boot-time check and serialization: a public path that a core GET route serves would open that route to anyone. */
|
|
151
|
-
export function assertPublicJson(publicJson) {
|
|
152
|
-
const bodies = new Map();
|
|
153
|
-
for (const [path, value] of Object.entries(publicJson)) {
|
|
154
|
-
if (!isPlainV1Path(path))
|
|
155
|
-
throw new Error(`public JSON path '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
|
|
156
|
-
if (isCorePath('GET', path))
|
|
157
|
-
throw new Error(`public JSON path '${path}' is already served by core`);
|
|
158
|
-
const text = JSON.stringify(value);
|
|
159
|
-
if (text === undefined)
|
|
160
|
-
throw new Error(`public JSON at '${path}' is not JSON`);
|
|
161
|
-
if (Buffer.byteLength(text) > PUBLIC_JSON_MAX_BYTES)
|
|
162
|
-
throw new Error(`public JSON at '${path}' is over 64 KiB`);
|
|
163
|
-
bodies.set(path, text);
|
|
164
|
-
}
|
|
165
|
-
return bodies;
|
|
166
|
-
}
|
|
167
168
|
/** Core authenticates and parses before the handler runs, so an add-on route gets the same 401, 400 and 501 as a core one. */
|
|
168
169
|
export async function dispatchAddonRoute({ req, res, opts }, method, path) {
|
|
169
170
|
const route = method === 'POST' ? opts.routes?.find((r) => r.path === path) : undefined;
|
|
170
171
|
if (!route)
|
|
171
172
|
return false;
|
|
172
173
|
noteAccess(req, { route: route.path });
|
|
173
|
-
await refuseUnportedRoute(req, opts, route.storeReady);
|
|
174
174
|
const ctx = await buildContextWithAuth(req, opts);
|
|
175
|
+
assertRoutePorted(opts, route.storeReady);
|
|
175
176
|
noteAccess(req, { tenant: ctx.tenantId });
|
|
176
177
|
const body = await parseJsonBody(req, ctx);
|
|
177
178
|
sendJson(res, 200, await route.handler({ ctx, body }));
|
|
@@ -187,16 +188,9 @@ export function dispatchPublicJson({ req, res, opts }, method, path) {
|
|
|
187
188
|
res.end(text);
|
|
188
189
|
return true;
|
|
189
190
|
}
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
/** A route answers 501 without running when the store lacks its group; a route that names none, a sqliteOnly one among them, needs hippo.db's local files. */
|
|
192
|
+
function assertRoutePorted(opts, group = 'localFiles') {
|
|
193
|
+
if (!hasGroup(opts.store, group))
|
|
192
194
|
throw new HttpError(501, STORE_NOT_PORTED_MESSAGE);
|
|
193
195
|
}
|
|
194
|
-
/** Under another store, a route that names no group, or one the store lacks, answers
|
|
195
|
-
* 501 without running; the caller is checked first, so a bad key is still a 401. */
|
|
196
|
-
async function refuseUnportedRoute(req, opts, group) {
|
|
197
|
-
if (opts.store.kind === 'sqlite' || (group !== undefined && hasGroup(opts.store, group)))
|
|
198
|
-
return;
|
|
199
|
-
await requireAuth(req, opts);
|
|
200
|
-
assertSqliteStore(opts);
|
|
201
|
-
}
|
|
202
196
|
//# sourceMappingURL=route-table.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function handleCreateAuthKey({ req, res, opts }:
|
|
3
|
-
export declare function handleListAuthKeys({
|
|
4
|
-
export declare function handleRevokeAuthKey({
|
|
5
|
-
export declare function handleListQuarantine({
|
|
6
|
-
export declare function handleApproveQuarantine({
|
|
7
|
-
export declare function handleRejectQuarantine({
|
|
8
|
-
export declare function handleListAudit({
|
|
1
|
+
import type { AuthedRouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateAuthKey({ req, res, opts }: AuthedRouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListAuthKeys({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleRevokeAuthKey({ res, ctx }: AuthedRouteRequest, keyMatch: Record<string, string>): Promise<void>;
|
|
5
|
+
export declare function handleListQuarantine({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
|
|
6
|
+
export declare function handleApproveQuarantine({ res, ctx }: AuthedRouteRequest, quarantineApproveMatch: Record<string, string>): Promise<void>;
|
|
7
|
+
export declare function handleRejectQuarantine({ res, ctx }: AuthedRouteRequest, quarantineRejectMatch: Record<string, string>): Promise<void>;
|
|
8
|
+
export declare function handleListAudit({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
|
|
9
9
|
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
// Admin routes: API keys, quarantine and the audit log.
|
|
2
|
+
import { DEFAULT_LIST_LIMIT } from '../../util/limits.js';
|
|
2
3
|
import { AUDIT_OPS } from '../../store/audit.js';
|
|
3
4
|
import { auditList, authCreate, authListRows, authRevoke, quarantineApprove, quarantineList, quarantineReject } from '../../api/index.js';
|
|
4
5
|
import { HttpError, readBody, sendJson } from '../../util/http-util.js';
|
|
5
|
-
import { assertCrossTenantAdmin,
|
|
6
|
+
import { assertCrossTenantAdmin, recheckContextWithAuth } from '../auth.js';
|
|
6
7
|
import { pageOf, parseCursor, setNextCursorHeader } from '../cursor.js';
|
|
7
8
|
import { isSetMember, parseJsonObjectText, parseListLimit, validateIdSegment } from '../validation.js';
|
|
8
9
|
import { isJsonBoolean, isJsonNumber, isJsonString } from '../../util/json.js';
|
|
9
10
|
const VALID_AUDIT_OPS = new Set(AUDIT_OPS);
|
|
10
|
-
//
|
|
11
|
+
// A key mint is a few short fields, so even an authenticated caller gets a small cap and a short wait.
|
|
11
12
|
// ServeOpts.mintBodyDeadlineMs overrides the wait for tests only, so a 408 test need not sit through it.
|
|
12
13
|
const MINT_BODY_MAX_BYTES = 4 * 1024;
|
|
13
14
|
const MINT_BODY_DEADLINE_MS = 10_000;
|
|
@@ -17,9 +18,9 @@ const MAX_AUDIT_LIMIT = 10000;
|
|
|
17
18
|
const MAX_AUTH_KEYS_PAGE = 1000;
|
|
18
19
|
// POST /v1/auth/keys: mints a key; plaintext is in the response body (the CLI client, not this layer, carries the "store this somewhere safe" warning).
|
|
19
20
|
export async function handleCreateAuthKey({ req, res, opts }) {
|
|
20
|
-
//
|
|
21
|
+
// The dispatch gate authenticated before the body, so an unknown caller costs no read; this recheck runs the resolver right before the mint.
|
|
21
22
|
const raw = await readBody(req, { maxBytes: MINT_BODY_MAX_BYTES, deadlineMs: opts.mintBodyDeadlineMs ?? MINT_BODY_DEADLINE_MS });
|
|
22
|
-
const ctx = await
|
|
23
|
+
const ctx = await recheckContextWithAuth(req, opts);
|
|
23
24
|
const body = parseJsonObjectText(raw);
|
|
24
25
|
const labelRaw = body['label'];
|
|
25
26
|
if (labelRaw !== undefined && !isJsonString(labelRaw)) {
|
|
@@ -56,7 +57,7 @@ export async function handleCreateAuthKey({ req, res, opts }) {
|
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
// GET /v1/auth/keys?active=true&limit=&cursor=: lists keys visible to ctx.tenantId; `active` defaults to true, ?active=false includes revoked and expired rows.
|
|
59
|
-
export async function handleListAuthKeys({
|
|
60
|
+
export async function handleListAuthKeys({ res, ctx, query }) {
|
|
60
61
|
const activeRaw = query.get('active');
|
|
61
62
|
let active = true;
|
|
62
63
|
if (activeRaw !== null) {
|
|
@@ -69,7 +70,6 @@ export async function handleListAuthKeys({ req, res, opts, query }) {
|
|
|
69
70
|
}
|
|
70
71
|
const limit = parseListLimit(query.get('limit'), MAX_AUTH_KEYS_PAGE, MAX_AUTH_KEYS_PAGE);
|
|
71
72
|
const after = parseCursor(query.get('cursor'), 'integer', 'integer');
|
|
72
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
73
73
|
const page = pageOf(await authListRows(ctx, { active, limit: limit + 1, after }), limit, (r) => ({ key: r.rowId, id: r.rowId }));
|
|
74
74
|
setNextCursorHeader(res, page.nextCursor);
|
|
75
75
|
sendJson(res, 200, page.items.map((r) => r.key));
|
|
@@ -77,19 +77,14 @@ export async function handleListAuthKeys({ req, res, opts, query }) {
|
|
|
77
77
|
}
|
|
78
78
|
// DELETE /v1/auth/keys/:keyId revokes: missing or cross-tenant keys are 404 (no leak); a member is 403 on any key but its own or, via the resolver, those it
|
|
79
79
|
// minted. Returns 200 with the body rather than 204 so the caller sees revokedAt.
|
|
80
|
-
export async function handleRevokeAuthKey({
|
|
80
|
+
export async function handleRevokeAuthKey({ res, ctx }, keyMatch) {
|
|
81
81
|
validateIdSegment(keyMatch.keyId, 'key id');
|
|
82
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
83
82
|
const result = await authRevoke(ctx, keyMatch.keyId);
|
|
84
83
|
sendJson(res, 200, result);
|
|
85
84
|
return;
|
|
86
85
|
}
|
|
87
|
-
// GET /v1/quarantine?status=&limit=&cursor=: quarantine review queue. quarantineList carries no role gate itself, so
|
|
88
|
-
export async function handleListQuarantine({
|
|
89
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
90
|
-
if (ctx.actor.role !== 'admin') {
|
|
91
|
-
throw new HttpError(403, '/v1/quarantine requires admin role');
|
|
92
|
-
}
|
|
86
|
+
// GET /v1/quarantine?status=&limit=&cursor=: quarantine review queue. quarantineList carries no role gate itself, so its row's admin gate is the check.
|
|
87
|
+
export async function handleListQuarantine({ res, ctx, query }) {
|
|
93
88
|
const statusRaw = query.get('status');
|
|
94
89
|
let status = 'pending';
|
|
95
90
|
if (statusRaw !== null) {
|
|
@@ -105,23 +100,21 @@ export async function handleListQuarantine({ req, res, opts, query }) {
|
|
|
105
100
|
return;
|
|
106
101
|
}
|
|
107
102
|
// POST /v1/quarantine/:id/approve: admin only; ForbiddenError falls through to mapApiError's 403.
|
|
108
|
-
export async function handleApproveQuarantine({
|
|
103
|
+
export async function handleApproveQuarantine({ res, ctx }, quarantineApproveMatch) {
|
|
109
104
|
validateIdSegment(quarantineApproveMatch.id, 'memory id');
|
|
110
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
111
105
|
await quarantineApprove(ctx, quarantineApproveMatch.id);
|
|
112
106
|
sendJson(res, 200, { approved: quarantineApproveMatch.id });
|
|
113
107
|
return;
|
|
114
108
|
}
|
|
115
109
|
// POST /v1/quarantine/:id/reject: admin only; ForbiddenError falls through to mapApiError's 403.
|
|
116
|
-
export async function handleRejectQuarantine({
|
|
110
|
+
export async function handleRejectQuarantine({ res, ctx }, quarantineRejectMatch) {
|
|
117
111
|
validateIdSegment(quarantineRejectMatch.id, 'memory id');
|
|
118
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
119
112
|
await quarantineReject(ctx, quarantineRejectMatch.id);
|
|
120
113
|
sendJson(res, 200, { rejected: quarantineRejectMatch.id });
|
|
121
114
|
return;
|
|
122
115
|
}
|
|
123
116
|
// GET /v1/audit?op=&since=&limit=&cursor=: all three filters are validated at the route boundary so an invalid value is a 400 before the DB is hit.
|
|
124
|
-
export async function handleListAudit({
|
|
117
|
+
export async function handleListAudit({ res, ctx, query }) {
|
|
125
118
|
const opRaw = query.get('op');
|
|
126
119
|
let op;
|
|
127
120
|
if (opRaw !== null) {
|
|
@@ -140,7 +133,7 @@ export async function handleListAudit({ req, res, opts, query }) {
|
|
|
140
133
|
since = sinceRaw;
|
|
141
134
|
}
|
|
142
135
|
const limitRaw = query.get('limit');
|
|
143
|
-
let limit =
|
|
136
|
+
let limit = DEFAULT_LIST_LIMIT;
|
|
144
137
|
if (limitRaw !== null) {
|
|
145
138
|
const parsed = Number(limitRaw);
|
|
146
139
|
if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed < 1 || parsed > MAX_AUDIT_LIMIT) {
|
|
@@ -149,7 +142,6 @@ export async function handleListAudit({ req, res, opts, query }) {
|
|
|
149
142
|
limit = parsed;
|
|
150
143
|
}
|
|
151
144
|
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
152
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
153
145
|
// ?tenant=<t> reads another tenant (e.g. '__host__' for consolidate rows); admin only.
|
|
154
146
|
const tenantOverride = query.get('tenant');
|
|
155
147
|
const crossTenant = tenantOverride !== null && tenantOverride !== '' && tenantOverride !== ctx.tenantId;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function handleCreateCustomerNote(rr:
|
|
3
|
-
export declare function handleListCustomerNotes(rr:
|
|
4
|
-
export declare function handleSupersedeCustomerNote(rr:
|
|
5
|
-
export declare function handleCloseCustomerNote(rr:
|
|
6
|
-
export declare function handleGetCustomerNote(rr:
|
|
1
|
+
import type { AuthedRouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateCustomerNote(rr: AuthedRouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListCustomerNotes(rr: AuthedRouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleSupersedeCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
5
|
+
export declare function handleCloseCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleGetCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
7
7
|
//# sourceMappingURL=customer-notes.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// /v1/customer-notes routes.
|
|
2
2
|
import { CUSTOMER_NOTE, MAX_CHANGE_SUMMARY_LEN, MAX_CUSTOMER_LEN } from '../../objects/customer-notes.js';
|
|
3
3
|
import { sendJson } from '../../util/http-util.js';
|
|
4
|
-
import { buildContextWithAuth } from '../auth.js';
|
|
5
4
|
import { parseJsonBody } from '../validation.js';
|
|
6
5
|
import { saveFor } from '../../api/objects.js';
|
|
7
6
|
import { closeRoute, getRoute, listRoute, optionalString, requiredString, supersedeRoute } from './object-routes.js';
|
|
@@ -20,7 +19,7 @@ const noteRoutes = {
|
|
|
20
19
|
// Routes: customer notes under /v1/customer-notes (create, list, show, supersede, close), mirroring /v1/project-briefs. The store validates and throws;
|
|
21
20
|
// the boundary maps validation -> 400, not-found -> 404, not-active -> 409.
|
|
22
21
|
export async function handleCreateCustomerNote(rr) {
|
|
23
|
-
const ctx =
|
|
22
|
+
const { ctx } = rr;
|
|
24
23
|
const body = await parseJsonBody(rr.req, ctx);
|
|
25
24
|
const customerNote = await saveFor(ctx, CUSTOMER_NOTE, {
|
|
26
25
|
customer: requiredString(body, 'customer', { max: MAX_CUSTOMER_LEN }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function handleCreateDecision(rr:
|
|
3
|
-
export declare function handleListDecisions(rr:
|
|
4
|
-
export declare function handleSupersedeDecision(rr:
|
|
5
|
-
export declare function handleCloseDecision(rr:
|
|
6
|
-
export declare function handleGetDecision(rr:
|
|
1
|
+
import type { AuthedRouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateDecision(rr: AuthedRouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListDecisions(rr: AuthedRouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleSupersedeDecision(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
5
|
+
export declare function handleCloseDecision(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleGetDecision(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
7
7
|
//# sourceMappingURL=decisions.d.ts.map
|
|
@@ -3,7 +3,6 @@ import { DECISION } from '../../objects/decisions.js';
|
|
|
3
3
|
import { HttpError, sendJson } from '../../util/http-util.js';
|
|
4
4
|
import { NotFoundError } from '../../core/api-errors.js';
|
|
5
5
|
import { isJsonNumber } from '../../util/json.js';
|
|
6
|
-
import { buildContextWithAuth } from '../auth.js';
|
|
7
6
|
import { MAX_SHORT_FIELD_LEN, parseJsonBody } from '../validation.js';
|
|
8
7
|
import { saveFor } from '../../api/objects.js';
|
|
9
8
|
import { closeRoute, getRoute, listRoute, optionalString, requiredString } from './object-routes.js';
|
|
@@ -21,8 +20,7 @@ function supersededId(body) {
|
|
|
21
20
|
// Routes: /v1/decisions (create, list, show, supersede, close), Bearer-authed and tenant-scoped; status is validated against VALID_DECISION_STATES.
|
|
22
21
|
// The HTTP surface has no legacy --supersedes <memory-id> constraint, so it supersedes by table id and never weakens a memory mirror.
|
|
23
22
|
export async function handleCreateDecision(rr) {
|
|
24
|
-
const { req, res } = rr;
|
|
25
|
-
const ctx = await buildContextWithAuth(req, rr.opts);
|
|
23
|
+
const { req, res, ctx } = rr;
|
|
26
24
|
const body = await parseJsonBody(req, ctx);
|
|
27
25
|
const write = {
|
|
28
26
|
decisionText: requiredString(body, 'text', TEXT),
|
|
@@ -46,7 +44,7 @@ export function handleListDecisions(rr) {
|
|
|
46
44
|
// Not on supersedeRoute: this one answers 201 and leaves the missing-row 404 to the store, where the other five answer 200 after their own lookup.
|
|
47
45
|
export async function handleSupersedeDecision(rr, match) {
|
|
48
46
|
const oldId = parseInt(match[1], 10);
|
|
49
|
-
const ctx =
|
|
47
|
+
const { ctx } = rr;
|
|
50
48
|
const body = await parseJsonBody(rr.req, ctx);
|
|
51
49
|
const decision = await saveFor(ctx, DECISION, {
|
|
52
50
|
decisionText: requiredString(body, 'text', TEXT),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function handleCreateIncident(rr:
|
|
3
|
-
export declare function handleListIncidents(rr:
|
|
4
|
-
export declare function handleResolveIncident(rr:
|
|
5
|
-
export declare function handleCloseIncident(rr:
|
|
6
|
-
export declare function handleGetIncident(rr:
|
|
1
|
+
import type { AuthedRouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateIncident(rr: AuthedRouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListIncidents(rr: AuthedRouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleResolveIncident(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
5
|
+
export declare function handleCloseIncident(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleGetIncident(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
|
|
7
7
|
//# sourceMappingURL=incidents.d.ts.map
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { INCIDENT, openIncident, resolveOpenIncident } from '../../objects/incidents.js';
|
|
3
3
|
import { HttpError, sendJson } from '../../util/http-util.js';
|
|
4
4
|
import { NotFoundError } from '../../core/api-errors.js';
|
|
5
|
-
import { buildContextWithAuth } from '../auth.js';
|
|
6
5
|
import { MAX_SHORT_FIELD_LEN, parseJsonBody } from '../validation.js';
|
|
7
6
|
import { isJsonString } from '../../util/json.js';
|
|
8
7
|
import { objectsOf } from '../../api/objects.js';
|
|
@@ -28,8 +27,7 @@ function linkedMemoryIds(body) {
|
|
|
28
27
|
// Routes: /v1/incidents (open, list, show, resolve, close), mirroring /v1/decisions; status is validated against VALID_INCIDENT_STATES.
|
|
29
28
|
// Lifecycle is open->resolved->closed (no supersede), so linkedMemoryIds replaces supersedesDecisionId on create.
|
|
30
29
|
export async function handleCreateIncident(rr) {
|
|
31
|
-
const { req, res, opts } = rr;
|
|
32
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
30
|
+
const { req, res, opts, ctx } = rr;
|
|
33
31
|
const body = await parseJsonBody(req, ctx);
|
|
34
32
|
const write = {
|
|
35
33
|
incidentText: requiredString(body, 'text', { max: MAX_SHORT_FIELD_LEN, untrimmed: true }),
|
|
@@ -51,9 +49,8 @@ export function handleListIncidents(rr) {
|
|
|
51
49
|
return listRoute(incidentRoutes, rr);
|
|
52
50
|
}
|
|
53
51
|
export async function handleResolveIncident(rr, match) {
|
|
54
|
-
const { req, res,
|
|
52
|
+
const { req, res, ctx } = rr;
|
|
55
53
|
const id = parseInt(match[1], 10);
|
|
56
|
-
const ctx = await buildContextWithAuth(req, opts);
|
|
57
54
|
const resolutionText = requiredString(await parseJsonBody(req, ctx), 'resolutionText', { max: MAX_SHORT_FIELD_LEN });
|
|
58
55
|
const incident = await resolveOpenIncident(objectsOf(ctx), ctx.tenantId, id, resolutionText, ctx.actor.subject);
|
|
59
56
|
sendJson(res, 200, { incident });
|