hippo-memory 1.30.0 → 1.31.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.
Files changed (105) hide show
  1. package/dist/api.d.ts +49 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +78 -2
  4. package/dist/api.js.map +1 -1
  5. package/dist/audit.d.ts +1 -1
  6. package/dist/audit.d.ts.map +1 -1
  7. package/dist/audit.js.map +1 -1
  8. package/dist/capture.d.ts.map +1 -1
  9. package/dist/capture.js +79 -23
  10. package/dist/capture.js.map +1 -1
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +233 -13
  14. package/dist/cli.js.map +1 -1
  15. package/dist/connectors/github/ingest.d.ts.map +1 -1
  16. package/dist/connectors/github/ingest.js +17 -0
  17. package/dist/connectors/github/ingest.js.map +1 -1
  18. package/dist/connectors/slack/ingest.d.ts.map +1 -1
  19. package/dist/connectors/slack/ingest.js +15 -0
  20. package/dist/connectors/slack/ingest.js.map +1 -1
  21. package/dist/consolidate.d.ts.map +1 -1
  22. package/dist/consolidate.js +428 -290
  23. package/dist/consolidate.js.map +1 -1
  24. package/dist/dag.d.ts +10 -0
  25. package/dist/dag.d.ts.map +1 -1
  26. package/dist/dag.js +32 -3
  27. package/dist/dag.js.map +1 -1
  28. package/dist/db.d.ts.map +1 -1
  29. package/dist/db.js +43 -1
  30. package/dist/db.js.map +1 -1
  31. package/dist/extract.d.ts.map +1 -1
  32. package/dist/extract.js +18 -1
  33. package/dist/extract.js.map +1 -1
  34. package/dist/importers.d.ts +10 -0
  35. package/dist/importers.d.ts.map +1 -1
  36. package/dist/importers.js +242 -159
  37. package/dist/importers.js.map +1 -1
  38. package/dist/mcp/server.d.ts.map +1 -1
  39. package/dist/mcp/server.js +34 -4
  40. package/dist/mcp/server.js.map +1 -1
  41. package/dist/reject-flow.d.ts +66 -0
  42. package/dist/reject-flow.d.ts.map +1 -0
  43. package/dist/reject-flow.js +207 -0
  44. package/dist/reject-flow.js.map +1 -0
  45. package/dist/rejection.d.ts +100 -0
  46. package/dist/rejection.d.ts.map +1 -0
  47. package/dist/rejection.js +157 -0
  48. package/dist/rejection.js.map +1 -0
  49. package/dist/server.d.ts.map +1 -1
  50. package/dist/server.js +4 -0
  51. package/dist/server.js.map +1 -1
  52. package/dist/shared.d.ts +9 -0
  53. package/dist/shared.d.ts.map +1 -1
  54. package/dist/shared.js +57 -6
  55. package/dist/shared.js.map +1 -1
  56. package/dist/sleep-redact.d.ts +2 -0
  57. package/dist/sleep-redact.d.ts.map +1 -1
  58. package/dist/sleep-redact.js +2 -0
  59. package/dist/sleep-redact.js.map +1 -1
  60. package/dist/src/api.js +78 -2
  61. package/dist/src/api.js.map +1 -1
  62. package/dist/src/audit.js.map +1 -1
  63. package/dist/src/capture.js +79 -23
  64. package/dist/src/capture.js.map +1 -1
  65. package/dist/src/cli.js +233 -13
  66. package/dist/src/cli.js.map +1 -1
  67. package/dist/src/connectors/github/ingest.js +17 -0
  68. package/dist/src/connectors/github/ingest.js.map +1 -1
  69. package/dist/src/connectors/slack/ingest.js +15 -0
  70. package/dist/src/connectors/slack/ingest.js.map +1 -1
  71. package/dist/src/consolidate.js +428 -290
  72. package/dist/src/consolidate.js.map +1 -1
  73. package/dist/src/dag.js +32 -3
  74. package/dist/src/dag.js.map +1 -1
  75. package/dist/src/db.js +43 -1
  76. package/dist/src/db.js.map +1 -1
  77. package/dist/src/extract.js +18 -1
  78. package/dist/src/extract.js.map +1 -1
  79. package/dist/src/importers.js +242 -159
  80. package/dist/src/importers.js.map +1 -1
  81. package/dist/src/mcp/server.js +34 -4
  82. package/dist/src/mcp/server.js.map +1 -1
  83. package/dist/src/reject-flow.js +207 -0
  84. package/dist/src/reject-flow.js.map +1 -0
  85. package/dist/src/rejection.js +157 -0
  86. package/dist/src/rejection.js.map +1 -0
  87. package/dist/src/server.js +4 -0
  88. package/dist/src/server.js.map +1 -1
  89. package/dist/src/shared.js +57 -6
  90. package/dist/src/shared.js.map +1 -1
  91. package/dist/src/sleep-redact.js +2 -0
  92. package/dist/src/sleep-redact.js.map +1 -1
  93. package/dist/src/store.js +498 -35
  94. package/dist/src/store.js.map +1 -1
  95. package/dist/src/version.js +1 -1
  96. package/dist/store.d.ts +107 -3
  97. package/dist/store.d.ts.map +1 -1
  98. package/dist/store.js +498 -35
  99. package/dist/store.js.map +1 -1
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.js +1 -1
  102. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  103. package/extensions/openclaw-plugin/package.json +1 -1
  104. package/openclaw.plugin.json +1 -1
  105. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * AT1 rejected-value tombstone — core invariant.
3
+ * docs/plans/2026-08-15-at1-rejected-value-tombstone.md
4
+ *
5
+ * Exact-normalized-value semantics: a human who rejects a fact can refuse
6
+ * byte-stable re-ingestion of the same value across remember/capture/import/
7
+ * sync surfaces. Paraphrase/semantic matching is explicitly out of scope
8
+ * (documented limitation, plan "Design").
9
+ *
10
+ * Kept db-agnostic (helpers take a `DatabaseSyncLike` handle) and does NOT
11
+ * import from store.ts — store.ts imports from here, and the reverse would
12
+ * be a cycle.
13
+ */
14
+ import type { DatabaseSyncLike } from './db.js';
15
+ /**
16
+ * Normalize content for rejection-digest comparisons: Unicode NFC →
17
+ * lowercase → collapse whitespace runs to a single space → trim. No
18
+ * punctuation stripping — over-normalization creates false refusals, which
19
+ * are worse than misses (plan §1).
20
+ */
21
+ export declare function normalizeValueForRejection(content: string): string;
22
+ /**
23
+ * Full sha256 hex (64 chars) of the normalized content. Reuses the strong-
24
+ * identity convention (importers.ts:814 content-hash tag), NOT the privacy-
25
+ * lossy 16-char convention (recall-trace query hashing) — a tombstone lookup
26
+ * key needs collision resistance, not redaction (plan §1).
27
+ */
28
+ export declare function rejectionDigest(content: string): string;
29
+ /**
30
+ * Thrown by the write-path guard (checkRejectionGuard, called from
31
+ * upsertEntryRow) when an incoming write would introduce a value matching a
32
+ * tombstoned digest. Carries enough context for the transaction-owner catch
33
+ * blocks (writeEntry, api.supersede) to write a post-rollback
34
+ * `reject_refusal` audit row via `auditRejectionRefusal` (plan §3).
35
+ */
36
+ export declare class RejectedValueError extends Error {
37
+ readonly digest: string;
38
+ readonly tenantId: string;
39
+ readonly entryId: string;
40
+ readonly reason: string | null;
41
+ readonly rejectedAt: string;
42
+ constructor(opts: {
43
+ digest: string;
44
+ tenantId: string;
45
+ entryId: string;
46
+ reason: string | null;
47
+ rejectedAt: string;
48
+ });
49
+ }
50
+ export interface RejectedValueRow {
51
+ tenantId: string;
52
+ digest: string;
53
+ reason: string | null;
54
+ rejectedBy: string | null;
55
+ rejectedAt: string;
56
+ sourceMemoryId: string | null;
57
+ normalizedChars: number | null;
58
+ }
59
+ /**
60
+ * Look up a tombstone by tenant + digest. One indexed point query — the
61
+ * guard's common-case cost, a miss ends the guard (plan §3).
62
+ */
63
+ export declare function findRejectedValue(db: DatabaseSyncLike, tenantId: string, digest: string): RejectedValueRow | null;
64
+ /**
65
+ * Insert (or refresh) a tombstone row. Caller owns the transaction — used by
66
+ * the T2 `reject` verb and `resolveConflict`'s `rejectLoserValue` path.
67
+ */
68
+ export declare function insertRejectedValue(db: DatabaseSyncLike, opts: {
69
+ tenantId: string;
70
+ digest: string;
71
+ reason: string;
72
+ rejectedBy: string;
73
+ rejectedAt: string;
74
+ sourceMemoryId?: string | null;
75
+ normalizedChars: number;
76
+ }): void;
77
+ /**
78
+ * Delete a tombstone by tenant + exact digest — the T2 `unreject` verb, the
79
+ * only v1 escape hatch (plan §4).
80
+ */
81
+ export declare function deleteRejectedValue(db: DatabaseSyncLike, tenantId: string, digest: string): boolean;
82
+ /** List tombstones for a tenant, newest first — the T2 `rejections` verb. */
83
+ export declare function listRejectedValues(db: DatabaseSyncLike, tenantId: string): RejectedValueRow[];
84
+ /**
85
+ * The write-path guard's check helper, called from `upsertEntryRow`
86
+ * (store.ts). Fires when the incoming content's digest matches a tombstone
87
+ * AND the write *introduces* that content: the row is new, OR the stored
88
+ * row's content digest differs from the incoming one — an UPSERT editing a
89
+ * same-id row TO a rejected value is a content introduction and must be
90
+ * refused. Unchanged same-id re-persists (recall boost, decay, star toggle)
91
+ * are exempt by construction (plan §3).
92
+ *
93
+ * Ordering minimizes queries on the common (miss) path: (a) caller has
94
+ * already computed nothing yet — this does the digest + point lookup first;
95
+ * (b) a miss returns immediately (ONE indexed point query); (c) only on a
96
+ * tombstone hit does it SELECT the stored row's content to classify
97
+ * new-row vs content-introduction (+1 query, rare path).
98
+ */
99
+ export declare function checkRejectionGuard(db: DatabaseSyncLike, tenantId: string, entryId: string, content: string): void;
100
+ //# sourceMappingURL=rejection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejection.d.ts","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACpB;CAYF;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAwBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,gBAAgB,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,gBAAgB,GAAG,IAAI,CAQzB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;CACzB,GACA,IAAI,CAmBN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnG;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAQ7F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,gBAAgB,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,IAAI,CAmCN"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * AT1 rejected-value tombstone — core invariant.
3
+ * docs/plans/2026-08-15-at1-rejected-value-tombstone.md
4
+ *
5
+ * Exact-normalized-value semantics: a human who rejects a fact can refuse
6
+ * byte-stable re-ingestion of the same value across remember/capture/import/
7
+ * sync surfaces. Paraphrase/semantic matching is explicitly out of scope
8
+ * (documented limitation, plan "Design").
9
+ *
10
+ * Kept db-agnostic (helpers take a `DatabaseSyncLike` handle) and does NOT
11
+ * import from store.ts — store.ts imports from here, and the reverse would
12
+ * be a cycle.
13
+ */
14
+ import { createHash } from 'node:crypto';
15
+ /**
16
+ * Normalize content for rejection-digest comparisons: Unicode NFC →
17
+ * lowercase → collapse whitespace runs to a single space → trim. No
18
+ * punctuation stripping — over-normalization creates false refusals, which
19
+ * are worse than misses (plan §1).
20
+ */
21
+ export function normalizeValueForRejection(content) {
22
+ return content.normalize('NFC').toLowerCase().replace(/\s+/g, ' ').trim();
23
+ }
24
+ /**
25
+ * Full sha256 hex (64 chars) of the normalized content. Reuses the strong-
26
+ * identity convention (importers.ts:814 content-hash tag), NOT the privacy-
27
+ * lossy 16-char convention (recall-trace query hashing) — a tombstone lookup
28
+ * key needs collision resistance, not redaction (plan §1).
29
+ */
30
+ export function rejectionDigest(content) {
31
+ return createHash('sha256').update(normalizeValueForRejection(content)).digest('hex');
32
+ }
33
+ /**
34
+ * Thrown by the write-path guard (checkRejectionGuard, called from
35
+ * upsertEntryRow) when an incoming write would introduce a value matching a
36
+ * tombstoned digest. Carries enough context for the transaction-owner catch
37
+ * blocks (writeEntry, api.supersede) to write a post-rollback
38
+ * `reject_refusal` audit row via `auditRejectionRefusal` (plan §3).
39
+ */
40
+ export class RejectedValueError extends Error {
41
+ digest;
42
+ tenantId;
43
+ entryId;
44
+ reason;
45
+ rejectedAt;
46
+ constructor(opts) {
47
+ super(`Memory value refused: matches a rejected value (digest ${opts.digest.slice(0, 12)}..., ` +
48
+ `reason: ${opts.reason ?? 'none given'}). Run "hippo unreject" to allow it again.`);
49
+ this.name = 'RejectedValueError';
50
+ this.digest = opts.digest;
51
+ this.tenantId = opts.tenantId;
52
+ this.entryId = opts.entryId;
53
+ this.reason = opts.reason;
54
+ this.rejectedAt = opts.rejectedAt;
55
+ }
56
+ }
57
+ function rowToRejectedValue(row) {
58
+ return {
59
+ tenantId: row.tenant_id,
60
+ digest: row.digest,
61
+ reason: row.reason,
62
+ rejectedBy: row.rejected_by,
63
+ rejectedAt: row.rejected_at,
64
+ sourceMemoryId: row.source_memory_id,
65
+ normalizedChars: row.normalized_chars,
66
+ };
67
+ }
68
+ /**
69
+ * Look up a tombstone by tenant + digest. One indexed point query — the
70
+ * guard's common-case cost, a miss ends the guard (plan §3).
71
+ */
72
+ export function findRejectedValue(db, tenantId, digest) {
73
+ const row = db
74
+ .prepare(`SELECT tenant_id, digest, reason, rejected_by, rejected_at, source_memory_id, normalized_chars
75
+ FROM rejected_values WHERE tenant_id = ? AND digest = ?`)
76
+ .get(tenantId, digest);
77
+ return row ? rowToRejectedValue(row) : null;
78
+ }
79
+ /**
80
+ * Insert (or refresh) a tombstone row. Caller owns the transaction — used by
81
+ * the T2 `reject` verb and `resolveConflict`'s `rejectLoserValue` path.
82
+ */
83
+ export function insertRejectedValue(db, opts) {
84
+ db.prepare(`INSERT INTO rejected_values(tenant_id, digest, reason, rejected_by, rejected_at, source_memory_id, normalized_chars)
85
+ VALUES (?, ?, ?, ?, ?, ?, ?)
86
+ ON CONFLICT(tenant_id, digest) DO UPDATE SET
87
+ reason = excluded.reason,
88
+ rejected_by = excluded.rejected_by,
89
+ rejected_at = excluded.rejected_at,
90
+ source_memory_id = excluded.source_memory_id,
91
+ normalized_chars = excluded.normalized_chars`).run(opts.tenantId, opts.digest, opts.reason, opts.rejectedBy, opts.rejectedAt, opts.sourceMemoryId ?? null, opts.normalizedChars);
92
+ }
93
+ /**
94
+ * Delete a tombstone by tenant + exact digest — the T2 `unreject` verb, the
95
+ * only v1 escape hatch (plan §4).
96
+ */
97
+ export function deleteRejectedValue(db, tenantId, digest) {
98
+ const result = db.prepare(`DELETE FROM rejected_values WHERE tenant_id = ? AND digest = ?`).run(tenantId, digest);
99
+ return (result.changes ?? 0) > 0;
100
+ }
101
+ /** List tombstones for a tenant, newest first — the T2 `rejections` verb. */
102
+ export function listRejectedValues(db, tenantId) {
103
+ const rows = db
104
+ .prepare(`SELECT tenant_id, digest, reason, rejected_by, rejected_at, source_memory_id, normalized_chars
105
+ FROM rejected_values WHERE tenant_id = ? ORDER BY rejected_at DESC, digest ASC`)
106
+ .all(tenantId);
107
+ return rows.map(rowToRejectedValue);
108
+ }
109
+ /**
110
+ * The write-path guard's check helper, called from `upsertEntryRow`
111
+ * (store.ts). Fires when the incoming content's digest matches a tombstone
112
+ * AND the write *introduces* that content: the row is new, OR the stored
113
+ * row's content digest differs from the incoming one — an UPSERT editing a
114
+ * same-id row TO a rejected value is a content introduction and must be
115
+ * refused. Unchanged same-id re-persists (recall boost, decay, star toggle)
116
+ * are exempt by construction (plan §3).
117
+ *
118
+ * Ordering minimizes queries on the common (miss) path: (a) caller has
119
+ * already computed nothing yet — this does the digest + point lookup first;
120
+ * (b) a miss returns immediately (ONE indexed point query); (c) only on a
121
+ * tombstone hit does it SELECT the stored row's content to classify
122
+ * new-row vs content-introduction (+1 query, rare path).
123
+ */
124
+ export function checkRejectionGuard(db, tenantId, entryId, content) {
125
+ const incomingDigest = rejectionDigest(content);
126
+ const tombstone = findRejectedValue(db, tenantId, incomingDigest);
127
+ if (!tombstone)
128
+ return; // miss ends the guard — the overwhelmingly common case
129
+ // Deliberately id-only (no tenant filter): memory ids are globally unique
130
+ // ULIDs, this lookup only classifies new-row vs same-id re-persist for the
131
+ // id the caller is already writing, and the tombstone lookup above is the
132
+ // tenant-scoped decision. Matches deleteEntry's own by-id SELECT.
133
+ //
134
+ // P2 fix: also read tenant_id. Content-digest-only comparison let a
135
+ // same-id upsert that ONLY changes tenantId slip through as an "unchanged
136
+ // re-persist" — content C sitting quietly (never rejected) in tenant A
137
+ // could be re-tagged into tenant B, and since C's digest already matched
138
+ // this row's stored digest, the guard exempted it even though B is the
139
+ // tenant that rejected C (that is WHY `tombstone` above is non-null: the
140
+ // lookup already ran under the INCOMING/destination tenantId). A tenant
141
+ // change on the SAME id is therefore always a content introduction into
142
+ // the destination tenant, exactly as if the row were new there.
143
+ const storedRow = db.prepare(`SELECT content, tenant_id FROM memories WHERE id = ?`).get(entryId);
144
+ const isNewRow = storedRow === undefined;
145
+ const tenantChanged = !isNewRow && storedRow.tenant_id !== tenantId;
146
+ const isContentIntroduction = isNewRow || tenantChanged || rejectionDigest(storedRow.content) !== incomingDigest;
147
+ if (!isContentIntroduction)
148
+ return; // unchanged same-id re-persist — exempt by construction
149
+ throw new RejectedValueError({
150
+ digest: incomingDigest,
151
+ tenantId,
152
+ entryId,
153
+ reason: tombstone.reason,
154
+ rejectedAt: tombstone.rejectedAt,
155
+ });
156
+ }
157
+ //# sourceMappingURL=rejection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejection.js","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyBA,kFAAkF;AAClF,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AA2QD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B;;;8BAG0B;IAC1B,MAAM,CAAC,EAAE,OAAO,WAAW,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0HD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAMrE;AAmrFD;;;;;;;;;;GAUG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CA0JlE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyBA,kFAAkF;AAClF,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AA+QD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B;;;8BAG0B;IAC1B,MAAM,CAAC,EAAE,OAAO,WAAW,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0HD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAMrE;AAmrFD;;;;;;;;;;GAUG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CA0JlE"}
package/dist/server.js CHANGED
@@ -109,6 +109,10 @@ const VALID_AUDIT_OPS = new Set([
109
109
  'customer_note_supersede', // E2 — emitted by saveCustomerNote on a supersession
110
110
  'customer_note_close', // E2 — emitted by closeCustomerNote
111
111
  'mv_rescue', // LC2-E3 — emitted by consolidate() per rescue; lockstep with AuditOp union + cli.ts VALID_AUDIT_OPS
112
+ 'reject_value', // AT1 — emitted by `hippo reject`; lockstep with AuditOp union + cli.ts VALID_AUDIT_OPS
113
+ 'reject_refusal', // AT1 — emitted when the rejection guard refuses a write; lockstep
114
+ 'unreject_value', // AT1 — emitted by `hippo unreject`; lockstep
115
+ 'conflict_resolve', // AT1 — emitted by resolveConflict on every resolution path; lockstep
112
116
  ]);
113
117
  // Cap on GET /v1/audit?limit=. Matches docs/api.md (when written) and is large
114
118
  // enough to dump a small deployment's full audit log without paginating, but