@gmickel/gno 1.27.1 → 1.29.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 +46 -20
- package/assets/skill/SKILL.md +59 -1
- package/browser-extension/artifacts/gno-browser-clipper-v1.29.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.29.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-b2zm0jjd.js +50 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +6 -6
- package/package.json +2 -2
- package/spec/cli.md +82 -5
- package/spec/db/schema.sql +31 -0
- package/spec/mcp.md +71 -0
- package/spec/output-schemas/ask.schema.json +156 -1
- package/spec/output-schemas/browser-clip-preview.schema.json +30 -0
- package/spec/output-schemas/collection-egress-check.schema.json +91 -0
- package/spec/output-schemas/collection-egress-policy-set.schema.json +56 -0
- package/spec/output-schemas/collection-egress-policy.schema.json +41 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +183 -3
- package/spec/output-schemas/context-capsule-verification.schema.json +1 -1
- package/spec/output-schemas/egress-audit-management.schema.json +88 -0
- package/spec/output-schemas/get.schema.json +94 -0
- package/spec/output-schemas/mcp-http-error.schema.json +113 -2
- package/spec/output-schemas/mcp-job-status.schema.json +28 -0
- package/spec/output-schemas/multi-get.schema.json +128 -0
- package/spec/output-schemas/publish-artifact.schema.json +32 -0
- package/spec/output-schemas/record-import.schema.json +223 -0
- package/spec/output-schemas/retrieval-trace-common.schema.json +31 -0
- package/spec/output-schemas/retrieval-trace-export.schema.json +3 -0
- package/spec/output-schemas/retrieval-trace-qrels.schema.json +3 -0
- package/spec/output-schemas/retrieval-trace-summary.schema.json +4 -0
- package/spec/output-schemas/search-result.schema.json +94 -0
- package/spec/output-schemas/search-results.schema.json +155 -0
- package/spec/project-profile.schema.json +66 -0
- package/src/app/context-format.ts +1 -1
- package/src/app/context-runtime-contract.ts +16 -7
- package/src/cli/commands/ask.ts +7 -0
- package/src/cli/commands/collection/index.ts +5 -0
- package/src/cli/commands/collection/policy.ts +126 -0
- package/src/cli/commands/context-build.ts +5 -0
- package/src/cli/commands/daemon.ts +45 -3
- package/src/cli/commands/egress-audit.ts +68 -0
- package/src/cli/commands/embed.ts +2 -0
- package/src/cli/commands/get.ts +12 -2
- package/src/cli/commands/index-cmd.ts +13 -0
- package/src/cli/commands/multi-get.ts +9 -2
- package/src/cli/commands/query.ts +12 -0
- package/src/cli/commands/replay.ts +13 -3
- package/src/cli/commands/shared.ts +28 -0
- package/src/cli/commands/update.ts +5 -0
- package/src/cli/commands/vsearch.ts +3 -1
- package/src/cli/program.ts +127 -0
- package/src/config/index.ts +9 -0
- package/src/config/project-profile.ts +2 -0
- package/src/config/types.ts +66 -0
- package/src/converters/adapters/browser-export/adapter.ts +199 -0
- package/src/converters/adapters/browser-export/formats.ts +358 -0
- package/src/converters/adapters/email/adapter.ts +429 -0
- package/src/converters/adapters/email/html.ts +162 -0
- package/src/converters/adapters/email/mime.ts +454 -0
- package/src/converters/adapters/email/parameters.ts +77 -0
- package/src/converters/adapters/ical/adapter.ts +475 -0
- package/src/converters/adapters/ical/recurrence.ts +186 -0
- package/src/converters/adapters/jsonl/adapter.ts +238 -0
- package/src/converters/adapters/jsonl/config.ts +105 -0
- package/src/converters/adapters/shared/html-text.ts +165 -0
- package/src/converters/adapters/shared/record-utils.ts +79 -0
- package/src/converters/adapters/shared/utf8-lines.ts +141 -0
- package/src/converters/adapters/transcript/adapter.ts +295 -0
- package/src/converters/adapters/transcript/json.ts +184 -0
- package/src/converters/adapters/transcript/model.ts +171 -0
- package/src/converters/adapters/transcript/text.ts +58 -0
- package/src/converters/adapters/transcript/timed.ts +152 -0
- package/src/converters/index.ts +11 -1
- package/src/converters/mime.ts +8 -0
- package/src/converters/pipeline.ts +15 -1
- package/src/converters/registry.ts +37 -1
- package/src/converters/types.ts +136 -0
- package/src/core/browser-clip.ts +16 -1
- package/src/core/collection-egress-policy-projection.ts +28 -0
- package/src/core/collection-egress-policy-service.ts +443 -0
- package/src/core/collection-egress-policy-validation.ts +242 -0
- package/src/core/config-mutation.ts +31 -19
- package/src/core/context-capsule-schema.ts +198 -1
- package/src/core/context-capsule-validation.ts +4 -4
- package/src/core/context-capsule-verification.ts +5 -1
- package/src/core/context-capsule.ts +177 -112
- package/src/core/context-evidence.ts +93 -15
- package/src/core/destination-classifier.ts +402 -0
- package/src/core/document-capabilities.ts +12 -0
- package/src/core/egress-audit.ts +239 -0
- package/src/core/egress-authorization.ts +50 -0
- package/src/core/egress-enforcement.ts +264 -0
- package/src/core/egress-policy.ts +440 -0
- package/src/core/egress-provenance.ts +336 -0
- package/src/core/job-manager.ts +37 -0
- package/src/core/network-boundary-inventory.ts +261 -0
- package/src/core/project-profile-apply-state.ts +5 -0
- package/src/core/project-profile.ts +4 -0
- package/src/core/record-metadata.ts +49 -0
- package/src/core/retrieval-qrels.ts +6 -0
- package/src/core/retrieval-replay.ts +18 -4
- package/src/core/retrieval-trace-export.ts +23 -4
- package/src/core/retrieval-trace-management-helpers.ts +1 -0
- package/src/core/retrieval-trace-management-types.ts +3 -0
- package/src/core/retrieval-trace-management.ts +9 -1
- package/src/core/retrieval-trace-session.ts +94 -0
- package/src/core/retrieval-trace.ts +22 -0
- package/src/ingestion/record-adapter-canonical.ts +433 -0
- package/src/ingestion/record-adapter.ts +448 -0
- package/src/ingestion/record-container.ts +704 -0
- package/src/ingestion/record-path.ts +20 -0
- package/src/ingestion/record-sync.ts +70 -0
- package/src/ingestion/sync.ts +243 -36
- package/src/ingestion/types.ts +71 -1
- package/src/ingestion/walker.ts +31 -11
- package/src/llm/errors.ts +10 -0
- package/src/llm/http-inference.ts +175 -0
- package/src/llm/http-policy.ts +537 -0
- package/src/llm/httpEmbedding.ts +47 -28
- package/src/llm/httpGeneration.ts +31 -18
- package/src/llm/httpRerank.ts +30 -18
- package/src/llm/index.ts +1 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +55 -20
- package/src/llm/pinned-http-connection.ts +177 -0
- package/src/mcp/context.ts +53 -1
- package/src/mcp/http-egress.ts +220 -0
- package/src/mcp/http-security.ts +32 -21
- package/src/mcp/http-session.ts +13 -2
- package/src/mcp/http-transport.ts +96 -6
- package/src/mcp/sync-egress.ts +24 -0
- package/src/mcp/tools/add-collection.ts +4 -0
- package/src/mcp/tools/ask.ts +1 -1
- package/src/mcp/tools/context.ts +9 -2
- package/src/mcp/tools/egress.ts +247 -0
- package/src/mcp/tools/embed.ts +1 -0
- package/src/mcp/tools/get.ts +10 -2
- package/src/mcp/tools/index-cmd.ts +7 -0
- package/src/mcp/tools/index.ts +98 -0
- package/src/mcp/tools/multi-get.ts +9 -2
- package/src/mcp/tools/query.ts +10 -0
- package/src/mcp/tools/remove-collection.ts +4 -0
- package/src/mcp/tools/sync.ts +6 -0
- package/src/mcp/tools/trace.ts +7 -1
- package/src/mcp/tools/vsearch.ts +1 -0
- package/src/mcp/tools/workspace-write.ts +2 -0
- package/src/pipeline/egress-lineage.ts +124 -0
- package/src/pipeline/filters.ts +1 -1
- package/src/pipeline/graph-retrieval.ts +7 -4
- package/src/pipeline/hybrid.ts +21 -4
- package/src/pipeline/result-context.ts +12 -4
- package/src/pipeline/search.ts +23 -4
- package/src/pipeline/types.ts +6 -0
- package/src/pipeline/vsearch.ts +67 -28
- package/src/publish/artifact.ts +31 -3
- package/src/publish/export-service.ts +25 -0
- package/src/sdk/client.ts +119 -2
- package/src/sdk/documents.ts +13 -5
- package/src/sdk/embed.ts +1 -0
- package/src/sdk/types.ts +33 -0
- package/src/serve/browse-tree.ts +4 -2
- package/src/serve/clipper-capture.ts +5 -1
- package/src/serve/closed-json.ts +61 -0
- package/src/serve/config-sync.ts +4 -1
- package/src/serve/context.ts +1 -0
- package/src/serve/doc-events.ts +110 -39
- package/src/serve/public/components/CollectionEgressCheckPanel.tsx +411 -0
- package/src/serve/public/components/CollectionEgressPolicyEditor.tsx +78 -0
- package/src/serve/public/components/CollectionModelDialog.tsx +93 -9
- package/src/serve/public/components/EgressAuditPanel.tsx +278 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/pages/Collections.tsx +3 -0
- package/src/serve/resident-request.ts +80 -3
- package/src/serve/resident-runtime.ts +63 -1
- package/src/serve/routes/api.ts +237 -65
- package/src/serve/routes/clipper.ts +64 -1
- package/src/serve/routes/mcp.ts +6 -0
- package/src/serve/routes/traces.ts +27 -4
- package/src/serve/server.ts +118 -7
- package/src/store/migrations/022-record-export-lineage.ts +42 -0
- package/src/store/migrations/023-collection-egress-policy.ts +61 -0
- package/src/store/migrations/024-egress-derived-lineage.ts +121 -0
- package/src/store/migrations/025-collection-egress-policy-revision.ts +40 -0
- package/src/store/migrations/index.ts +8 -0
- package/src/store/retrieval-trace-codec.ts +15 -0
- package/src/store/sqlite/adapter.ts +284 -14
- package/src/store/sqlite/change-journal-store.ts +41 -2
- package/src/store/sqlite/egress-audit-store.ts +485 -0
- package/src/store/sqlite/retrieval-trace-management-store.ts +47 -6
- package/src/store/sqlite/retrieval-trace-retention.ts +2 -0
- package/src/store/sqlite/retrieval-trace-rows.ts +8 -1
- package/src/store/sqlite/retrieval-trace-store.ts +104 -5
- package/src/store/types.ts +166 -1
- package/browser-extension/artifacts/gno-browser-clipper-v1.27.1.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.27.1.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-vn5f663b.js +0 -50
|
@@ -15,7 +15,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
15
15
|
// node:path basename: no Bun path utilities.
|
|
16
16
|
import { basename } from "node:path";
|
|
17
17
|
|
|
18
|
-
import type {
|
|
18
|
+
import type { EgressLineage } from "../../core/egress-provenance";
|
|
19
19
|
import type {
|
|
20
20
|
ActivationIndexDocument,
|
|
21
21
|
ActivationIndexIdentity,
|
|
@@ -44,6 +44,15 @@ import type {
|
|
|
44
44
|
DocumentInput,
|
|
45
45
|
DocumentRow,
|
|
46
46
|
EmbeddingCleanupStats,
|
|
47
|
+
EgressAuditCursor,
|
|
48
|
+
EgressAuditDeleteResult,
|
|
49
|
+
EgressAuditPage,
|
|
50
|
+
EgressAuditPurgeResult,
|
|
51
|
+
EgressAuditReceiptInput,
|
|
52
|
+
EgressAuditReceiptRow,
|
|
53
|
+
EgressAuditRetentionPolicy,
|
|
54
|
+
EgressAuditRetentionResult,
|
|
55
|
+
EgressAuditStatusResult,
|
|
47
56
|
FtsResult,
|
|
48
57
|
FtsSearchOptions,
|
|
49
58
|
GetGraphOptions,
|
|
@@ -93,6 +102,14 @@ import type {
|
|
|
93
102
|
import type { SqliteDbProvider } from "./types";
|
|
94
103
|
|
|
95
104
|
import { buildUri, deriveDocid, stripUriIndex } from "../../app/constants";
|
|
105
|
+
import {
|
|
106
|
+
type Collection,
|
|
107
|
+
type Context,
|
|
108
|
+
type EgressPolicy,
|
|
109
|
+
type EgressPolicySource,
|
|
110
|
+
type FtsTokenizer,
|
|
111
|
+
resolveConfiguredEgressPolicy,
|
|
112
|
+
} from "../../config/types";
|
|
96
113
|
import { analyzeGraphCommunities } from "../../core/graph-analysis";
|
|
97
114
|
import {
|
|
98
115
|
buildWikiBestMatchSubquery,
|
|
@@ -127,6 +144,16 @@ import {
|
|
|
127
144
|
purgeDocumentChanges as purgeStoredDocumentChanges,
|
|
128
145
|
snapshotDocumentChange,
|
|
129
146
|
} from "./change-journal-store";
|
|
147
|
+
import {
|
|
148
|
+
appendEgressAuditReceipt as appendStoredEgressAuditReceipt,
|
|
149
|
+
appendEgressAuditReceiptWithRetention as appendStoredEgressAuditReceiptWithRetention,
|
|
150
|
+
deleteEgressAuditReceipt as deleteStoredEgressAuditReceipt,
|
|
151
|
+
enforceEgressAuditRetention as enforceStoredEgressAuditRetention,
|
|
152
|
+
getEgressAuditReceipt as getStoredEgressAuditReceipt,
|
|
153
|
+
getEgressAuditStatus as getStoredEgressAuditStatus,
|
|
154
|
+
listEgressAuditReceipts as listStoredEgressAuditReceipts,
|
|
155
|
+
purgeEgressAuditReceipts as purgeStoredEgressAuditReceipts,
|
|
156
|
+
} from "./egress-audit-store";
|
|
130
157
|
import { loadFts5Snowball } from "./fts5-snowball";
|
|
131
158
|
import {
|
|
132
159
|
appendExportManifest as appendStoredTraceExportManifest,
|
|
@@ -149,6 +176,7 @@ import {
|
|
|
149
176
|
finalizeTrace as finalizeStoredTrace,
|
|
150
177
|
getTrace as getStoredTrace,
|
|
151
178
|
listTraces as listStoredTraces,
|
|
179
|
+
mergeTraceEgressLineage as mergeStoredTraceEgressLineage,
|
|
152
180
|
} from "./retrieval-trace-store";
|
|
153
181
|
|
|
154
182
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -589,8 +617,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
589
617
|
|
|
590
618
|
// Upsert collections
|
|
591
619
|
const stmt = db.prepare(`
|
|
592
|
-
INSERT INTO collections (
|
|
593
|
-
|
|
620
|
+
INSERT INTO collections (
|
|
621
|
+
name, path, pattern, include, exclude, update_cmd, language_hint,
|
|
622
|
+
egress_policy, egress_policy_source, egress_policy_revision,
|
|
623
|
+
synced_at
|
|
624
|
+
)
|
|
625
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
594
626
|
ON CONFLICT(name) DO UPDATE SET
|
|
595
627
|
path = excluded.path,
|
|
596
628
|
pattern = excluded.pattern,
|
|
@@ -598,10 +630,29 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
598
630
|
exclude = excluded.exclude,
|
|
599
631
|
update_cmd = excluded.update_cmd,
|
|
600
632
|
language_hint = excluded.language_hint,
|
|
633
|
+
egress_policy = CASE
|
|
634
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
635
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
636
|
+
THEN collections.egress_policy
|
|
637
|
+
ELSE excluded.egress_policy
|
|
638
|
+
END,
|
|
639
|
+
egress_policy_source = CASE
|
|
640
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
641
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
642
|
+
THEN collections.egress_policy_source
|
|
643
|
+
ELSE excluded.egress_policy_source
|
|
644
|
+
END,
|
|
645
|
+
egress_policy_revision = CASE
|
|
646
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
647
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
648
|
+
THEN collections.egress_policy_revision
|
|
649
|
+
ELSE excluded.egress_policy_revision
|
|
650
|
+
END,
|
|
601
651
|
synced_at = datetime('now')
|
|
602
652
|
`);
|
|
603
653
|
|
|
604
654
|
for (const c of collections) {
|
|
655
|
+
const egress = resolveConfiguredEgressPolicy(c);
|
|
605
656
|
stmt.run(
|
|
606
657
|
c.name,
|
|
607
658
|
c.path,
|
|
@@ -609,7 +660,10 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
609
660
|
c.include.length > 0 ? JSON.stringify(c.include) : null,
|
|
610
661
|
c.exclude.length > 0 ? JSON.stringify(c.exclude) : null,
|
|
611
662
|
c.updateCmd ?? null,
|
|
612
|
-
c.languageHint ?? null
|
|
663
|
+
c.languageHint ?? null,
|
|
664
|
+
egress.policy,
|
|
665
|
+
egress.source,
|
|
666
|
+
c.egressPolicyRevision ?? 0
|
|
613
667
|
);
|
|
614
668
|
}
|
|
615
669
|
});
|
|
@@ -631,8 +685,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
631
685
|
try {
|
|
632
686
|
const db = this.ensureOpen();
|
|
633
687
|
const stmt = db.prepare(`
|
|
634
|
-
INSERT INTO collections (
|
|
635
|
-
|
|
688
|
+
INSERT INTO collections (
|
|
689
|
+
name, path, pattern, include, exclude, update_cmd, language_hint,
|
|
690
|
+
egress_policy, egress_policy_source, egress_policy_revision,
|
|
691
|
+
synced_at
|
|
692
|
+
)
|
|
693
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
636
694
|
ON CONFLICT(name) DO UPDATE SET
|
|
637
695
|
path = excluded.path,
|
|
638
696
|
pattern = excluded.pattern,
|
|
@@ -640,6 +698,24 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
640
698
|
exclude = excluded.exclude,
|
|
641
699
|
update_cmd = excluded.update_cmd,
|
|
642
700
|
language_hint = excluded.language_hint,
|
|
701
|
+
egress_policy = CASE
|
|
702
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
703
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
704
|
+
THEN collections.egress_policy
|
|
705
|
+
ELSE excluded.egress_policy
|
|
706
|
+
END,
|
|
707
|
+
egress_policy_source = CASE
|
|
708
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
709
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
710
|
+
THEN collections.egress_policy_source
|
|
711
|
+
ELSE excluded.egress_policy_source
|
|
712
|
+
END,
|
|
713
|
+
egress_policy_revision = CASE
|
|
714
|
+
WHEN excluded.egress_policy_source = 'config_default'
|
|
715
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
716
|
+
THEN collections.egress_policy_revision
|
|
717
|
+
ELSE excluded.egress_policy_revision
|
|
718
|
+
END,
|
|
643
719
|
synced_at = datetime('now')
|
|
644
720
|
WHERE collections.path IS NOT excluded.path
|
|
645
721
|
OR collections.pattern IS NOT excluded.pattern
|
|
@@ -647,9 +723,21 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
647
723
|
OR collections.exclude IS NOT excluded.exclude
|
|
648
724
|
OR collections.update_cmd IS NOT excluded.update_cmd
|
|
649
725
|
OR collections.language_hint IS NOT excluded.language_hint
|
|
726
|
+
OR (
|
|
727
|
+
NOT (
|
|
728
|
+
excluded.egress_policy_source = 'config_default'
|
|
729
|
+
AND collections.egress_policy_source = 'legacy_default'
|
|
730
|
+
)
|
|
731
|
+
AND (
|
|
732
|
+
collections.egress_policy IS NOT excluded.egress_policy
|
|
733
|
+
OR collections.egress_policy_source IS NOT excluded.egress_policy_source
|
|
734
|
+
OR collections.egress_policy_revision IS NOT excluded.egress_policy_revision
|
|
735
|
+
)
|
|
736
|
+
)
|
|
650
737
|
`);
|
|
651
738
|
const transaction = db.transaction(() => {
|
|
652
739
|
for (const collection of collections) {
|
|
740
|
+
const egress = resolveConfiguredEgressPolicy(collection);
|
|
653
741
|
stmt.run(
|
|
654
742
|
collection.name,
|
|
655
743
|
collection.path,
|
|
@@ -661,7 +749,10 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
661
749
|
? JSON.stringify(collection.exclude)
|
|
662
750
|
: null,
|
|
663
751
|
collection.updateCmd ?? null,
|
|
664
|
-
collection.languageHint ?? null
|
|
752
|
+
collection.languageHint ?? null,
|
|
753
|
+
egress.policy,
|
|
754
|
+
egress.source,
|
|
755
|
+
collection.egressPolicyRevision ?? 0
|
|
665
756
|
);
|
|
666
757
|
}
|
|
667
758
|
});
|
|
@@ -943,6 +1034,13 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
943
1034
|
return createStoredTrace(this.ensureOpen(), input);
|
|
944
1035
|
}
|
|
945
1036
|
|
|
1037
|
+
async mergeRetrievalTraceEgressLineage(
|
|
1038
|
+
traceId: string,
|
|
1039
|
+
lineage: EgressLineage
|
|
1040
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>> {
|
|
1041
|
+
return mergeStoredTraceEgressLineage(this.ensureOpen(), traceId, lineage);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
946
1044
|
async getRetrievalTrace(
|
|
947
1045
|
traceId: string
|
|
948
1046
|
): Promise<StoreResult<RetrievalTraceBundle | null>> {
|
|
@@ -1038,6 +1136,61 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1038
1136
|
return enforceStoredTraceRetention(this.ensureOpen(), policy, nowMs);
|
|
1039
1137
|
}
|
|
1040
1138
|
|
|
1139
|
+
async appendEgressAuditReceipt(
|
|
1140
|
+
receipt: EgressAuditReceiptInput
|
|
1141
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>> {
|
|
1142
|
+
return appendStoredEgressAuditReceipt(this.ensureOpen(), receipt);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
async appendEgressAuditReceiptWithRetention(
|
|
1146
|
+
receipt: EgressAuditReceiptInput,
|
|
1147
|
+
policy: EgressAuditRetentionPolicy,
|
|
1148
|
+
nowMs: number
|
|
1149
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>> {
|
|
1150
|
+
return appendStoredEgressAuditReceiptWithRetention(
|
|
1151
|
+
this.ensureOpen(),
|
|
1152
|
+
receipt,
|
|
1153
|
+
policy,
|
|
1154
|
+
nowMs
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
async listEgressAuditReceipts(
|
|
1159
|
+
limit: number,
|
|
1160
|
+
cursor?: EgressAuditCursor
|
|
1161
|
+
): Promise<StoreResult<EgressAuditPage>> {
|
|
1162
|
+
return listStoredEgressAuditReceipts(this.ensureOpen(), limit, cursor);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
async getEgressAuditReceipt(
|
|
1166
|
+
auditId: string
|
|
1167
|
+
): Promise<StoreResult<EgressAuditReceiptRow | null>> {
|
|
1168
|
+
return getStoredEgressAuditReceipt(this.ensureOpen(), auditId);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
async deleteEgressAuditReceipt(
|
|
1172
|
+
auditId: string
|
|
1173
|
+
): Promise<StoreResult<EgressAuditDeleteResult>> {
|
|
1174
|
+
return deleteStoredEgressAuditReceipt(this.ensureOpen(), auditId);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
async getEgressAuditStatus(): Promise<StoreResult<EgressAuditStatusResult>> {
|
|
1178
|
+
return getStoredEgressAuditStatus(this.ensureOpen());
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
async enforceEgressAuditRetention(
|
|
1182
|
+
policy: EgressAuditRetentionPolicy,
|
|
1183
|
+
nowMs: number
|
|
1184
|
+
): Promise<StoreResult<EgressAuditRetentionResult>> {
|
|
1185
|
+
return enforceStoredEgressAuditRetention(this.ensureOpen(), policy, nowMs);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
async purgeEgressAuditReceipts(): Promise<
|
|
1189
|
+
StoreResult<EgressAuditPurgeResult>
|
|
1190
|
+
> {
|
|
1191
|
+
return purgeStoredEgressAuditReceipts(this.ensureOpen());
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1041
1194
|
getContextGeneration(): number {
|
|
1042
1195
|
return this.contextGeneration;
|
|
1043
1196
|
}
|
|
@@ -1067,10 +1220,13 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1067
1220
|
collection, rel_path, source_hash, source_mime, source_ext,
|
|
1068
1221
|
source_size, source_mtime, source_ctime, docid, uri, title, mirror_hash,
|
|
1069
1222
|
converter_id, converter_version, language_hint, content_type, categories,
|
|
1070
|
-
content_type_source, author, frontmatter_date, date_fields,
|
|
1223
|
+
content_type_source, author, frontmatter_date, date_fields,
|
|
1224
|
+
record_key, record_source_path, record_source_locator, record_metadata, record_anchors,
|
|
1225
|
+
record_adapter_fingerprint,
|
|
1226
|
+
content_type_rules_fingerprint,
|
|
1071
1227
|
active, indexed_at, last_error_code, last_error_message, last_error_at,
|
|
1072
1228
|
ingest_version, updated_at
|
|
1073
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, datetime('now'), ?, ?, ?, ?, datetime('now'))
|
|
1229
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, datetime('now'), ?, ?, ?, ?, datetime('now'))
|
|
1074
1230
|
ON CONFLICT(collection, rel_path) DO UPDATE SET
|
|
1075
1231
|
source_hash = excluded.source_hash,
|
|
1076
1232
|
source_mime = excluded.source_mime,
|
|
@@ -1091,6 +1247,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1091
1247
|
author = excluded.author,
|
|
1092
1248
|
frontmatter_date = excluded.frontmatter_date,
|
|
1093
1249
|
date_fields = excluded.date_fields,
|
|
1250
|
+
record_key = excluded.record_key,
|
|
1251
|
+
record_source_path = excluded.record_source_path,
|
|
1252
|
+
record_source_locator = excluded.record_source_locator,
|
|
1253
|
+
record_metadata = excluded.record_metadata,
|
|
1254
|
+
record_anchors = excluded.record_anchors,
|
|
1255
|
+
record_adapter_fingerprint = excluded.record_adapter_fingerprint,
|
|
1094
1256
|
content_type_rules_fingerprint = excluded.content_type_rules_fingerprint,
|
|
1095
1257
|
active = 1,
|
|
1096
1258
|
indexed_at = datetime('now'),
|
|
@@ -1122,6 +1284,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1122
1284
|
doc.author ?? null,
|
|
1123
1285
|
doc.frontmatterDate ?? null,
|
|
1124
1286
|
doc.dateFields ? JSON.stringify(doc.dateFields) : null,
|
|
1287
|
+
doc.recordKey ?? null,
|
|
1288
|
+
doc.recordSourcePath ?? null,
|
|
1289
|
+
doc.recordSourceLocator ?? null,
|
|
1290
|
+
doc.recordMetadata ? JSON.stringify(doc.recordMetadata) : null,
|
|
1291
|
+
doc.recordAnchors ? JSON.stringify(doc.recordAnchors) : null,
|
|
1292
|
+
doc.recordAdapterFingerprint ?? null,
|
|
1125
1293
|
doc.contentTypeRulesFingerprint ?? null,
|
|
1126
1294
|
doc.lastErrorCode ?? null,
|
|
1127
1295
|
doc.lastErrorMessage ?? null,
|
|
@@ -1366,6 +1534,32 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1366
1534
|
}
|
|
1367
1535
|
}
|
|
1368
1536
|
|
|
1537
|
+
async listRecordDocuments(
|
|
1538
|
+
collection: string,
|
|
1539
|
+
sourcePath: string
|
|
1540
|
+
): Promise<StoreResult<DocumentRow[]>> {
|
|
1541
|
+
try {
|
|
1542
|
+
const db = this.ensureOpen();
|
|
1543
|
+
const rows = db
|
|
1544
|
+
.query<DbDocumentRow, [string, string]>(
|
|
1545
|
+
`SELECT * FROM documents
|
|
1546
|
+
WHERE collection = ? AND record_source_path = ?
|
|
1547
|
+
ORDER BY rel_path ASC, id ASC`
|
|
1548
|
+
)
|
|
1549
|
+
.all(collection, sourcePath);
|
|
1550
|
+
|
|
1551
|
+
return ok(rows.map(mapDocumentRow));
|
|
1552
|
+
} catch (cause) {
|
|
1553
|
+
return err(
|
|
1554
|
+
"QUERY_FAILED",
|
|
1555
|
+
cause instanceof Error
|
|
1556
|
+
? cause.message
|
|
1557
|
+
: "Failed to list record documents",
|
|
1558
|
+
cause
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1369
1563
|
async listActiveDocumentsForBrowse(
|
|
1370
1564
|
collection?: string
|
|
1371
1565
|
): Promise<StoreResult<DocumentRow[]>> {
|
|
@@ -1547,17 +1741,18 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
1547
1741
|
const normalizedPathPrefix = pathPrefix
|
|
1548
1742
|
?.replaceAll("\\", "/")
|
|
1549
1743
|
.replace(/^\/+|\/+$/g, "");
|
|
1744
|
+
const browsePathSql = "COALESCE(d.record_source_path, d.rel_path)";
|
|
1550
1745
|
|
|
1551
1746
|
if (normalizedPathPrefix) {
|
|
1552
|
-
conditions.push(
|
|
1747
|
+
conditions.push(`${browsePathSql} LIKE ?`);
|
|
1553
1748
|
params.push(`${normalizedPathPrefix}/%`);
|
|
1554
1749
|
|
|
1555
1750
|
if (directChildrenOnly) {
|
|
1556
|
-
conditions.push(
|
|
1751
|
+
conditions.push(`substr(${browsePathSql}, ?) NOT LIKE '%/%'`);
|
|
1557
1752
|
params.push(normalizedPathPrefix.length + 2);
|
|
1558
1753
|
}
|
|
1559
1754
|
} else if (directChildrenOnly) {
|
|
1560
|
-
conditions.push(
|
|
1755
|
+
conditions.push(`${browsePathSql} NOT LIKE '%/%'`);
|
|
1561
1756
|
}
|
|
1562
1757
|
|
|
1563
1758
|
if (options.since) {
|
|
@@ -2162,7 +2357,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
2162
2357
|
${options.collection ? "AND collection = ?" : ""}
|
|
2163
2358
|
${
|
|
2164
2359
|
options.relPathPrefix !== undefined
|
|
2165
|
-
? "AND (rel_path = ? OR substr(rel_path, 1, length(?) + 1) = ? || '/')"
|
|
2360
|
+
? "AND (COALESCE(NULLIF(record_source_path, ''), rel_path) = ? OR substr(COALESCE(NULLIF(record_source_path, ''), rel_path), 1, length(?) + 1) = ? || '/')"
|
|
2166
2361
|
: ""
|
|
2167
2362
|
}
|
|
2168
2363
|
)
|
|
@@ -2187,7 +2382,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
2187
2382
|
d.source_hash,
|
|
2188
2383
|
d.content_type,
|
|
2189
2384
|
d.content_type_source,
|
|
2190
|
-
d.categories
|
|
2385
|
+
d.categories,
|
|
2386
|
+
d.converter_id,
|
|
2387
|
+
d.converter_version,
|
|
2388
|
+
d.record_key,
|
|
2389
|
+
d.record_source_path,
|
|
2390
|
+
d.record_source_locator,
|
|
2391
|
+
d.record_metadata,
|
|
2392
|
+
d.record_anchors,
|
|
2393
|
+
d.record_adapter_fingerprint
|
|
2191
2394
|
FROM fts_matches fm
|
|
2192
2395
|
JOIN documents d ON d.id = fm.rowid AND d.active = 1
|
|
2193
2396
|
WHERE 1 = 1
|
|
@@ -2215,6 +2418,14 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
2215
2418
|
content_type: string | null;
|
|
2216
2419
|
content_type_source: string | null;
|
|
2217
2420
|
categories: string | null;
|
|
2421
|
+
converter_id: string | null;
|
|
2422
|
+
converter_version: string | null;
|
|
2423
|
+
record_key: string | null;
|
|
2424
|
+
record_source_path: string | null;
|
|
2425
|
+
record_source_locator: string | null;
|
|
2426
|
+
record_metadata: string | null;
|
|
2427
|
+
record_anchors: string | null;
|
|
2428
|
+
record_adapter_fingerprint: string | null;
|
|
2218
2429
|
}
|
|
2219
2430
|
|
|
2220
2431
|
const queryParams = [
|
|
@@ -2254,6 +2465,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
2254
2465
|
contentType: r.content_type ?? undefined,
|
|
2255
2466
|
contentTypeSource: r.content_type_source ?? undefined,
|
|
2256
2467
|
categories: parseCategoriesJson(r.categories) ?? undefined,
|
|
2468
|
+
converterId: r.converter_id ?? undefined,
|
|
2469
|
+
converterVersion: r.converter_version ?? undefined,
|
|
2470
|
+
recordKey: r.record_key ?? undefined,
|
|
2471
|
+
recordSourcePath: r.record_source_path ?? undefined,
|
|
2472
|
+
recordSourceLocator: r.record_source_locator ?? undefined,
|
|
2473
|
+
recordMetadata:
|
|
2474
|
+
parseRecordMetadataJson(r.record_metadata) ?? undefined,
|
|
2475
|
+
recordAnchors: parseRecordAnchorsJson(r.record_anchors) ?? undefined,
|
|
2476
|
+
recordAdapterFingerprint: r.record_adapter_fingerprint ?? undefined,
|
|
2257
2477
|
}))
|
|
2258
2478
|
);
|
|
2259
2479
|
} catch (cause) {
|
|
@@ -4642,6 +4862,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
4642
4862
|
interface CollectionStat {
|
|
4643
4863
|
name: string;
|
|
4644
4864
|
path: string;
|
|
4865
|
+
egress_policy: EgressPolicy;
|
|
4866
|
+
egress_policy_source: EgressPolicySource;
|
|
4645
4867
|
total: number;
|
|
4646
4868
|
active: number;
|
|
4647
4869
|
errored: number;
|
|
@@ -4693,6 +4915,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
4693
4915
|
SELECT
|
|
4694
4916
|
c.name,
|
|
4695
4917
|
c.path,
|
|
4918
|
+
c.egress_policy,
|
|
4919
|
+
c.egress_policy_source,
|
|
4696
4920
|
COALESCE(ds.total, 0) AS total,
|
|
4697
4921
|
COALESCE(ds.active, 0) AS active,
|
|
4698
4922
|
COALESCE(ds.errored, 0) AS errored,
|
|
@@ -4789,6 +5013,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
|
|
|
4789
5013
|
collections: collectionStats.map((s) => ({
|
|
4790
5014
|
name: s.name,
|
|
4791
5015
|
path: s.path,
|
|
5016
|
+
egressPolicy: s.egress_policy,
|
|
5017
|
+
egressPolicySource: s.egress_policy_source,
|
|
4792
5018
|
totalDocuments: s.total,
|
|
4793
5019
|
activeDocuments: s.active,
|
|
4794
5020
|
errorDocuments: s.errored,
|
|
@@ -5065,6 +5291,8 @@ interface DbCollectionRow {
|
|
|
5065
5291
|
exclude: string | null;
|
|
5066
5292
|
update_cmd: string | null;
|
|
5067
5293
|
language_hint: string | null;
|
|
5294
|
+
egress_policy: EgressPolicy;
|
|
5295
|
+
egress_policy_source: EgressPolicySource;
|
|
5068
5296
|
synced_at: string;
|
|
5069
5297
|
}
|
|
5070
5298
|
|
|
@@ -5098,6 +5326,12 @@ interface DbDocumentRow {
|
|
|
5098
5326
|
author: string | null;
|
|
5099
5327
|
frontmatter_date: string | null;
|
|
5100
5328
|
date_fields: string | null;
|
|
5329
|
+
record_key: string | null;
|
|
5330
|
+
record_source_path: string | null;
|
|
5331
|
+
record_source_locator: string | null;
|
|
5332
|
+
record_metadata: string | null;
|
|
5333
|
+
record_anchors: string | null;
|
|
5334
|
+
record_adapter_fingerprint: string | null;
|
|
5101
5335
|
content_type_rules_fingerprint: string | null;
|
|
5102
5336
|
indexed_at: string | null;
|
|
5103
5337
|
active: number;
|
|
@@ -5157,6 +5391,8 @@ function mapCollectionRow(row: DbCollectionRow): CollectionRow {
|
|
|
5157
5391
|
exclude: row.exclude ? JSON.parse(row.exclude) : null,
|
|
5158
5392
|
updateCmd: row.update_cmd,
|
|
5159
5393
|
languageHint: row.language_hint,
|
|
5394
|
+
egressPolicy: row.egress_policy,
|
|
5395
|
+
egressPolicySource: row.egress_policy_source,
|
|
5160
5396
|
syncedAt: row.synced_at,
|
|
5161
5397
|
};
|
|
5162
5398
|
}
|
|
@@ -5185,6 +5421,34 @@ function parseCategoriesJson(raw: string | null): string[] | null {
|
|
|
5185
5421
|
return null;
|
|
5186
5422
|
}
|
|
5187
5423
|
|
|
5424
|
+
function parseRecordMetadataJson(
|
|
5425
|
+
raw: string | null
|
|
5426
|
+
): DocumentRow["recordMetadata"] {
|
|
5427
|
+
if (!raw) return null;
|
|
5428
|
+
try {
|
|
5429
|
+
const parsed: unknown = JSON.parse(raw);
|
|
5430
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
5431
|
+
? (parsed as NonNullable<DocumentRow["recordMetadata"]>)
|
|
5432
|
+
: null;
|
|
5433
|
+
} catch {
|
|
5434
|
+
return null;
|
|
5435
|
+
}
|
|
5436
|
+
}
|
|
5437
|
+
|
|
5438
|
+
function parseRecordAnchorsJson(
|
|
5439
|
+
raw: string | null
|
|
5440
|
+
): DocumentRow["recordAnchors"] {
|
|
5441
|
+
if (!raw) return null;
|
|
5442
|
+
try {
|
|
5443
|
+
const parsed: unknown = JSON.parse(raw);
|
|
5444
|
+
return Array.isArray(parsed)
|
|
5445
|
+
? (parsed as NonNullable<DocumentRow["recordAnchors"]>)
|
|
5446
|
+
: null;
|
|
5447
|
+
} catch {
|
|
5448
|
+
return null;
|
|
5449
|
+
}
|
|
5450
|
+
}
|
|
5451
|
+
|
|
5188
5452
|
function mapDocumentRow(row: DbDocumentRow): DocumentRow {
|
|
5189
5453
|
const categories = parseCategoriesJson(row.categories);
|
|
5190
5454
|
let dateFields: Record<string, string> | null = null;
|
|
@@ -5230,6 +5494,12 @@ function mapDocumentRow(row: DbDocumentRow): DocumentRow {
|
|
|
5230
5494
|
author: row.author,
|
|
5231
5495
|
frontmatterDate: row.frontmatter_date,
|
|
5232
5496
|
dateFields,
|
|
5497
|
+
recordKey: row.record_key,
|
|
5498
|
+
recordSourcePath: row.record_source_path,
|
|
5499
|
+
recordSourceLocator: row.record_source_locator,
|
|
5500
|
+
recordMetadata: parseRecordMetadataJson(row.record_metadata),
|
|
5501
|
+
recordAnchors: parseRecordAnchorsJson(row.record_anchors),
|
|
5502
|
+
recordAdapterFingerprint: row.record_adapter_fingerprint,
|
|
5233
5503
|
indexedAt: row.indexed_at,
|
|
5234
5504
|
active: row.active === 1,
|
|
5235
5505
|
ingestVersion: row.ingest_version,
|
|
@@ -22,6 +22,10 @@ import {
|
|
|
22
22
|
serializeDocumentChangeStructureDelta,
|
|
23
23
|
validateDocumentChangeRetentionPolicy,
|
|
24
24
|
} from "../../core/change-journal";
|
|
25
|
+
import {
|
|
26
|
+
createEgressLineage,
|
|
27
|
+
egressLineageSchema,
|
|
28
|
+
} from "../../core/egress-provenance";
|
|
25
29
|
import { err, ok } from "../types";
|
|
26
30
|
|
|
27
31
|
const DAY_MS = 86_400_000;
|
|
@@ -74,6 +78,8 @@ interface DbDocumentChangeRow {
|
|
|
74
78
|
structure_truncated: number;
|
|
75
79
|
observed_at_ms: number;
|
|
76
80
|
byte_size: number;
|
|
81
|
+
egress_lineage_json: string;
|
|
82
|
+
egress_lineage_bytes: number;
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
const utf8ByteLength = (value: string | null): number =>
|
|
@@ -127,6 +133,7 @@ const mapRow = (row: DbDocumentChangeRow): DocumentChangeRow => ({
|
|
|
127
133
|
dates: JSON.parse(row.date_delta_json),
|
|
128
134
|
truncated: row.structure_truncated === 1,
|
|
129
135
|
},
|
|
136
|
+
egressLineage: egressLineageSchema.parse(JSON.parse(row.egress_lineage_json)),
|
|
130
137
|
observedAtMs: row.observed_at_ms,
|
|
131
138
|
byteSize: row.byte_size,
|
|
132
139
|
});
|
|
@@ -249,11 +256,38 @@ export const appendDocumentChange = (
|
|
|
249
256
|
} = serializeDocumentChangeStructureDelta(draft.structureDelta);
|
|
250
257
|
const old = draft.oldSnapshot;
|
|
251
258
|
const next = draft.newSnapshot;
|
|
259
|
+
const collectionPolicy = db
|
|
260
|
+
.query<
|
|
261
|
+
{
|
|
262
|
+
egress_policy: "local_only" | "lan" | "remote";
|
|
263
|
+
egress_policy_source: "explicit" | "config_default" | "legacy_default";
|
|
264
|
+
},
|
|
265
|
+
[string]
|
|
266
|
+
>(
|
|
267
|
+
`SELECT egress_policy, egress_policy_source
|
|
268
|
+
FROM collections WHERE name = ?`
|
|
269
|
+
)
|
|
270
|
+
.get(draft.collection);
|
|
271
|
+
if (!collectionPolicy) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
`Document change policy lineage references unknown collection ${draft.collection}`
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
const egressLineage = createEgressLineage([
|
|
277
|
+
{
|
|
278
|
+
collection: draft.collection,
|
|
279
|
+
policy: collectionPolicy.egress_policy,
|
|
280
|
+
source: collectionPolicy.egress_policy_source,
|
|
281
|
+
},
|
|
282
|
+
]);
|
|
283
|
+
const egressLineageJson = JSON.stringify(egressLineage);
|
|
284
|
+
const egressLineageBytes = UTF8_ENCODER.encode(egressLineageJson).byteLength;
|
|
252
285
|
const storedByteSize = byteSize(draft, [
|
|
253
286
|
headingDeltaJson,
|
|
254
287
|
linkDeltaJson,
|
|
255
288
|
typedEdgeDeltaJson,
|
|
256
289
|
dateDeltaJson,
|
|
290
|
+
egressLineageJson,
|
|
257
291
|
]);
|
|
258
292
|
const inserted = db.run(
|
|
259
293
|
`INSERT INTO document_changes (
|
|
@@ -262,8 +296,9 @@ export const appendDocumentChange = (
|
|
|
262
296
|
old_source_hash, new_source_hash, old_mirror_hash, new_mirror_hash,
|
|
263
297
|
old_active, new_active, heading_delta_json, link_delta_json,
|
|
264
298
|
typed_edge_delta_json, date_delta_json, structure_truncated,
|
|
265
|
-
|
|
266
|
-
|
|
299
|
+
effective_egress_policy, egress_lineage_digest, egress_lineage_json,
|
|
300
|
+
egress_lineage_bytes, observed_at_ms, byte_size
|
|
301
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
267
302
|
[
|
|
268
303
|
draft.documentId,
|
|
269
304
|
draft.collection,
|
|
@@ -285,6 +320,10 @@ export const appendDocumentChange = (
|
|
|
285
320
|
typedEdgeDeltaJson,
|
|
286
321
|
dateDeltaJson,
|
|
287
322
|
delta.truncated ? 1 : 0,
|
|
323
|
+
egressLineage.effectivePolicy,
|
|
324
|
+
egressLineage.digest,
|
|
325
|
+
egressLineageJson,
|
|
326
|
+
egressLineageBytes,
|
|
288
327
|
draft.observedAtMs,
|
|
289
328
|
storedByteSize,
|
|
290
329
|
]
|