@gmickel/gno 1.20.0 → 1.22.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 +29 -5
- package/assets/skill/SKILL.md +46 -15
- package/package.json +2 -1
- package/spec/cli.md +144 -0
- package/spec/db/schema.sql +170 -0
- package/spec/evals-agentic.md +48 -0
- package/spec/mcp.md +22 -0
- package/spec/output-schemas/capsule-reverified-event.schema.json +47 -0
- package/spec/output-schemas/changes.schema.json +280 -0
- package/spec/output-schemas/document-diff.schema.json +185 -0
- package/spec/output-schemas/impact.schema.json +122 -0
- package/spec/output-schemas/publish-artifact.schema.json +284 -0
- package/spec/output-schemas/saved-capsule-list.schema.json +16 -0
- package/spec/output-schemas/saved-capsule-registration.schema.json +172 -0
- package/spec/output-schemas/saved-capsule-reverification.schema.json +59 -0
- package/spec/output-schemas/saved-capsule-unwatch.schema.json +16 -0
- package/spec/output-schemas/saved-capsule-watch.schema.json +17 -0
- package/src/cli/commands/changes.ts +160 -0
- package/src/cli/commands/context-saved.ts +189 -0
- package/src/cli/options.ts +8 -0
- package/src/cli/program.ts +195 -0
- package/src/core/capsule-registry.ts +279 -0
- package/src/core/capsule-reverification-scheduler.ts +218 -0
- package/src/core/capsule-reverification.ts +289 -0
- package/src/core/change-diff.ts +182 -0
- package/src/core/change-journal.ts +228 -0
- package/src/core/knowledge-delta.ts +395 -0
- package/src/core/knowledge-impact.ts +202 -0
- package/src/ingestion/sync.ts +214 -165
- package/src/mcp/tools/changes.ts +80 -0
- package/src/mcp/tools/index.ts +29 -0
- package/src/publish/artifact-validation.ts +259 -0
- package/src/publish/artifact.ts +234 -118
- package/src/publish/export-service.ts +5 -9
- package/src/publish/metadata.ts +195 -0
- package/src/sdk/client.ts +42 -0
- package/src/sdk/index.ts +7 -0
- package/src/sdk/types.ts +22 -0
- package/src/serve/doc-events.ts +12 -1
- package/src/serve/resident-runtime.ts +22 -0
- package/src/serve/routes/api.ts +13 -0
- package/src/serve/routes/changes.ts +102 -0
- package/src/serve/server.ts +34 -0
- package/src/serve/watch-service.ts +9 -0
- package/src/store/index.ts +21 -0
- package/src/store/migrations/015-document-change-journal.ts +85 -0
- package/src/store/migrations/016-saved-capsules.ts +131 -0
- package/src/store/migrations/017-document-change-retention-counters.ts +33 -0
- package/src/store/migrations/018-saved-capsule-registration-epoch.ts +24 -0
- package/src/store/migrations/019-saved-capsule-registration-generation.ts +53 -0
- package/src/store/migrations/index.ts +10 -0
- package/src/store/sqlite/adapter.ts +291 -7
- package/src/store/sqlite/capsule-registry-store.ts +534 -0
- package/src/store/sqlite/change-journal-store.ts +473 -0
- package/src/store/types.ts +262 -0
package/src/store/index.ts
CHANGED
|
@@ -33,6 +33,16 @@ export type {
|
|
|
33
33
|
CollectionRow,
|
|
34
34
|
CollectionStatus,
|
|
35
35
|
ContextRow,
|
|
36
|
+
DocumentChangeDateDelta,
|
|
37
|
+
DocumentChangeKind,
|
|
38
|
+
DocumentChangeListOptions,
|
|
39
|
+
DocumentChangePage,
|
|
40
|
+
DocumentChangePurgeResult,
|
|
41
|
+
DocumentChangeRetentionPolicy,
|
|
42
|
+
DocumentChangeRetentionResult,
|
|
43
|
+
DocumentChangeRow,
|
|
44
|
+
DocumentChangeSet,
|
|
45
|
+
DocumentChangeStructureDelta,
|
|
36
46
|
DocumentInput,
|
|
37
47
|
DocumentRow,
|
|
38
48
|
FtsResult,
|
|
@@ -72,6 +82,17 @@ export type {
|
|
|
72
82
|
RetrievalTraceRunRow,
|
|
73
83
|
RetrievalTraceStatus,
|
|
74
84
|
RetrievalTraceTerminalStatus,
|
|
85
|
+
RenameDocumentOptions,
|
|
86
|
+
SavedCapsuleAffectedQuestionState,
|
|
87
|
+
SavedCapsuleEvidenceReference,
|
|
88
|
+
SavedCapsuleNotificationPreference,
|
|
89
|
+
SavedCapsuleOperationStatus,
|
|
90
|
+
SavedCapsuleRegistration,
|
|
91
|
+
SavedCapsuleRegistrationInput,
|
|
92
|
+
SavedCapsuleRegistrationRecord,
|
|
93
|
+
SavedCapsuleReverificationState,
|
|
94
|
+
SavedCapsuleTriggerKind,
|
|
95
|
+
SavedCapsuleVerificationRecord,
|
|
75
96
|
StoreError,
|
|
76
97
|
StoreErrorCode,
|
|
77
98
|
StorePort,
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: bounded, metadata-only document change journal.
|
|
3
|
+
*
|
|
4
|
+
* The journal intentionally stores document identity, hashes, active state,
|
|
5
|
+
* and compact structural summaries. Source and converted document bodies are
|
|
6
|
+
* never copied into this table.
|
|
7
|
+
*
|
|
8
|
+
* @module src/store/migrations/015-document-change-journal
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Database } from "bun:sqlite";
|
|
12
|
+
|
|
13
|
+
import type { Migration } from "./runner";
|
|
14
|
+
|
|
15
|
+
export const migration: Migration = {
|
|
16
|
+
version: 15,
|
|
17
|
+
name: "document_change_journal",
|
|
18
|
+
|
|
19
|
+
up(db: Database): void {
|
|
20
|
+
db.exec(`
|
|
21
|
+
CREATE TABLE document_changes (
|
|
22
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
document_id INTEGER NOT NULL CHECK (document_id > 0),
|
|
24
|
+
collection TEXT NOT NULL,
|
|
25
|
+
change_kind TEXT NOT NULL
|
|
26
|
+
CHECK (change_kind IN ('create', 'update', 'rename', 'inactivate', 'reactivate')),
|
|
27
|
+
old_rel_path TEXT,
|
|
28
|
+
new_rel_path TEXT,
|
|
29
|
+
old_docid TEXT,
|
|
30
|
+
new_docid TEXT,
|
|
31
|
+
old_uri TEXT,
|
|
32
|
+
new_uri TEXT,
|
|
33
|
+
old_source_hash TEXT,
|
|
34
|
+
new_source_hash TEXT,
|
|
35
|
+
old_mirror_hash TEXT,
|
|
36
|
+
new_mirror_hash TEXT,
|
|
37
|
+
old_active INTEGER CHECK (old_active IS NULL OR old_active IN (0, 1)),
|
|
38
|
+
new_active INTEGER CHECK (new_active IS NULL OR new_active IN (0, 1)),
|
|
39
|
+
heading_delta_json TEXT NOT NULL DEFAULT '{"added":[],"removed":[]}',
|
|
40
|
+
link_delta_json TEXT NOT NULL DEFAULT '{"added":[],"removed":[]}',
|
|
41
|
+
typed_edge_delta_json TEXT NOT NULL DEFAULT '{"added":[],"removed":[]}',
|
|
42
|
+
date_delta_json TEXT NOT NULL DEFAULT '{"added":[],"removed":[],"changed":[]}',
|
|
43
|
+
structure_truncated INTEGER NOT NULL DEFAULT 0
|
|
44
|
+
CHECK (structure_truncated IN (0, 1)),
|
|
45
|
+
observed_at_ms INTEGER NOT NULL CHECK (observed_at_ms >= 0),
|
|
46
|
+
byte_size INTEGER NOT NULL CHECK (byte_size > 0 AND byte_size <= 131072),
|
|
47
|
+
CHECK (length(CAST(collection AS BLOB)) BETWEEN 1 AND 256),
|
|
48
|
+
CHECK (old_rel_path IS NULL OR length(CAST(old_rel_path AS BLOB)) BETWEEN 1 AND 4096),
|
|
49
|
+
CHECK (new_rel_path IS NULL OR length(CAST(new_rel_path AS BLOB)) BETWEEN 1 AND 4096),
|
|
50
|
+
CHECK (old_docid IS NULL OR length(CAST(old_docid AS BLOB)) BETWEEN 1 AND 256),
|
|
51
|
+
CHECK (new_docid IS NULL OR length(CAST(new_docid AS BLOB)) BETWEEN 1 AND 256),
|
|
52
|
+
CHECK (old_uri IS NULL OR length(CAST(old_uri AS BLOB)) BETWEEN 1 AND 8192),
|
|
53
|
+
CHECK (new_uri IS NULL OR length(CAST(new_uri AS BLOB)) BETWEEN 1 AND 8192),
|
|
54
|
+
CHECK (old_source_hash IS NULL OR length(CAST(old_source_hash AS BLOB)) BETWEEN 1 AND 256),
|
|
55
|
+
CHECK (new_source_hash IS NULL OR length(CAST(new_source_hash AS BLOB)) BETWEEN 1 AND 256),
|
|
56
|
+
CHECK (old_mirror_hash IS NULL OR length(CAST(old_mirror_hash AS BLOB)) BETWEEN 1 AND 256),
|
|
57
|
+
CHECK (new_mirror_hash IS NULL OR length(CAST(new_mirror_hash AS BLOB)) BETWEEN 1 AND 256),
|
|
58
|
+
CHECK (length(CAST(heading_delta_json AS BLOB)) <= 16384),
|
|
59
|
+
CHECK (length(CAST(link_delta_json AS BLOB)) <= 16384),
|
|
60
|
+
CHECK (length(CAST(typed_edge_delta_json AS BLOB)) <= 16384),
|
|
61
|
+
CHECK (length(CAST(date_delta_json AS BLOB)) <= 16384)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
CREATE INDEX idx_document_changes_collection_sequence
|
|
65
|
+
ON document_changes(collection, sequence);
|
|
66
|
+
|
|
67
|
+
CREATE INDEX idx_document_changes_document_sequence
|
|
68
|
+
ON document_changes(document_id, sequence);
|
|
69
|
+
|
|
70
|
+
CREATE INDEX idx_document_changes_retention
|
|
71
|
+
ON document_changes(observed_at_ms, sequence);
|
|
72
|
+
|
|
73
|
+
CREATE TABLE document_change_journal_state (
|
|
74
|
+
singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 1),
|
|
75
|
+
last_sequence INTEGER NOT NULL DEFAULT 0 CHECK (last_sequence >= 0),
|
|
76
|
+
retention_floor INTEGER NOT NULL DEFAULT 0
|
|
77
|
+
CHECK (retention_floor >= 0 AND retention_floor <= last_sequence)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
INSERT INTO document_change_journal_state (
|
|
81
|
+
singleton_id, last_sequence, retention_floor
|
|
82
|
+
) VALUES (1, 0, 0);
|
|
83
|
+
`);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: metadata-only saved Context Capsule registry.
|
|
3
|
+
*
|
|
4
|
+
* Capsule bodies remain user-owned files. The database stores only file and
|
|
5
|
+
* Capsule identities, evidence references, the latest verification outcome,
|
|
6
|
+
* and the journal high-water sequence used by the resident scheduler.
|
|
7
|
+
*
|
|
8
|
+
* @module src/store/migrations/016-saved-capsules
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Database } from "bun:sqlite";
|
|
12
|
+
|
|
13
|
+
import type { Migration } from "./runner";
|
|
14
|
+
|
|
15
|
+
export const migration: Migration = {
|
|
16
|
+
version: 16,
|
|
17
|
+
name: "saved_capsules",
|
|
18
|
+
|
|
19
|
+
up(db: Database): void {
|
|
20
|
+
db.exec(`
|
|
21
|
+
CREATE TABLE saved_capsule_registrations (
|
|
22
|
+
registration_id TEXT PRIMARY KEY,
|
|
23
|
+
file_path TEXT NOT NULL UNIQUE,
|
|
24
|
+
file_hash TEXT NOT NULL,
|
|
25
|
+
capsule_id TEXT NOT NULL,
|
|
26
|
+
index_name TEXT NOT NULL,
|
|
27
|
+
question TEXT,
|
|
28
|
+
label TEXT,
|
|
29
|
+
notification_preference TEXT NOT NULL DEFAULT 'none'
|
|
30
|
+
CHECK (notification_preference IN ('none', 'local')),
|
|
31
|
+
registered_at_ms INTEGER NOT NULL CHECK (registered_at_ms >= 0),
|
|
32
|
+
updated_at_ms INTEGER NOT NULL CHECK (updated_at_ms >= registered_at_ms),
|
|
33
|
+
last_attempted_sequence INTEGER NOT NULL DEFAULT 0
|
|
34
|
+
CHECK (last_attempted_sequence >= 0),
|
|
35
|
+
CHECK (length(registration_id) BETWEEN 1 AND 128),
|
|
36
|
+
CHECK (length(CAST(file_path AS BLOB)) BETWEEN 1 AND 8192),
|
|
37
|
+
CHECK (length(file_hash) = 64 AND file_hash NOT GLOB '*[^0-9a-f]*'),
|
|
38
|
+
CHECK (length(capsule_id) = 64 AND capsule_id NOT GLOB '*[^0-9a-f]*'),
|
|
39
|
+
CHECK (length(CAST(index_name AS BLOB)) BETWEEN 1 AND 128),
|
|
40
|
+
CHECK (question IS NULL OR length(CAST(question AS BLOB)) <= 8192),
|
|
41
|
+
CHECK (label IS NULL OR length(CAST(label AS BLOB)) <= 512)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX idx_saved_capsules_index
|
|
45
|
+
ON saved_capsule_registrations(index_name, registration_id);
|
|
46
|
+
|
|
47
|
+
CREATE TABLE saved_capsule_evidence (
|
|
48
|
+
registration_id TEXT NOT NULL,
|
|
49
|
+
evidence_id TEXT NOT NULL,
|
|
50
|
+
canonical_uri TEXT NOT NULL,
|
|
51
|
+
collection TEXT NOT NULL,
|
|
52
|
+
source_hash TEXT NOT NULL,
|
|
53
|
+
mirror_hash TEXT NOT NULL,
|
|
54
|
+
passage_hash TEXT NOT NULL,
|
|
55
|
+
PRIMARY KEY (registration_id, evidence_id),
|
|
56
|
+
FOREIGN KEY (registration_id)
|
|
57
|
+
REFERENCES saved_capsule_registrations(registration_id)
|
|
58
|
+
ON DELETE CASCADE,
|
|
59
|
+
CHECK (length(evidence_id) = 64 AND evidence_id NOT GLOB '*[^0-9a-f]*'),
|
|
60
|
+
CHECK (length(CAST(canonical_uri AS BLOB)) BETWEEN 1 AND 8192),
|
|
61
|
+
CHECK (length(CAST(collection AS BLOB)) BETWEEN 1 AND 256),
|
|
62
|
+
CHECK (length(source_hash) = 64 AND source_hash NOT GLOB '*[^0-9a-f]*'),
|
|
63
|
+
CHECK (length(mirror_hash) = 64 AND mirror_hash NOT GLOB '*[^0-9a-f]*'),
|
|
64
|
+
CHECK (length(passage_hash) = 64 AND passage_hash NOT GLOB '*[^0-9a-f]*')
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
CREATE INDEX idx_saved_capsule_evidence_uri
|
|
68
|
+
ON saved_capsule_evidence(canonical_uri, registration_id);
|
|
69
|
+
|
|
70
|
+
CREATE INDEX idx_saved_capsule_evidence_source
|
|
71
|
+
ON saved_capsule_evidence(source_hash, registration_id);
|
|
72
|
+
|
|
73
|
+
CREATE INDEX idx_saved_capsule_evidence_mirror
|
|
74
|
+
ON saved_capsule_evidence(mirror_hash, registration_id);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE saved_capsule_verifications (
|
|
77
|
+
registration_id TEXT PRIMARY KEY,
|
|
78
|
+
trigger_kind TEXT NOT NULL CHECK (trigger_kind IN ('manual', 'journal')),
|
|
79
|
+
from_sequence INTEGER NOT NULL CHECK (from_sequence >= 0),
|
|
80
|
+
through_sequence INTEGER NOT NULL
|
|
81
|
+
CHECK (through_sequence >= from_sequence),
|
|
82
|
+
operation_status TEXT NOT NULL CHECK (operation_status IN ('completed', 'failed')),
|
|
83
|
+
affected_question_state TEXT NOT NULL
|
|
84
|
+
CHECK (affected_question_state IN ('unaffected', 'affected', 'unknown')),
|
|
85
|
+
affected_reasons_json TEXT NOT NULL,
|
|
86
|
+
receipt_json TEXT,
|
|
87
|
+
receipt_hash TEXT,
|
|
88
|
+
error_code TEXT,
|
|
89
|
+
error_message TEXT,
|
|
90
|
+
verified_at_ms INTEGER NOT NULL CHECK (verified_at_ms >= 0),
|
|
91
|
+
FOREIGN KEY (registration_id)
|
|
92
|
+
REFERENCES saved_capsule_registrations(registration_id)
|
|
93
|
+
ON DELETE CASCADE,
|
|
94
|
+
CHECK (length(CAST(affected_reasons_json AS BLOB)) <= 4096),
|
|
95
|
+
CHECK (receipt_json IS NULL OR length(CAST(receipt_json AS BLOB)) <= 16777216),
|
|
96
|
+
CHECK (receipt_hash IS NULL OR (
|
|
97
|
+
length(receipt_hash) = 64 AND receipt_hash NOT GLOB '*[^0-9a-f]*'
|
|
98
|
+
)),
|
|
99
|
+
CHECK (error_code IS NULL OR length(CAST(error_code AS BLOB)) <= 256),
|
|
100
|
+
CHECK (error_message IS NULL OR length(CAST(error_message AS BLOB)) <= 4096),
|
|
101
|
+
CHECK (
|
|
102
|
+
(
|
|
103
|
+
operation_status = 'completed'
|
|
104
|
+
AND receipt_json IS NOT NULL
|
|
105
|
+
AND receipt_hash IS NOT NULL
|
|
106
|
+
AND error_code IS NULL
|
|
107
|
+
AND error_message IS NULL
|
|
108
|
+
)
|
|
109
|
+
OR
|
|
110
|
+
(
|
|
111
|
+
operation_status = 'failed'
|
|
112
|
+
AND receipt_json IS NULL
|
|
113
|
+
AND receipt_hash IS NULL
|
|
114
|
+
AND error_code IS NOT NULL
|
|
115
|
+
AND error_message IS NOT NULL
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
CREATE TABLE saved_capsule_reverification_state (
|
|
121
|
+
singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 1),
|
|
122
|
+
last_processed_sequence INTEGER NOT NULL DEFAULT 0
|
|
123
|
+
CHECK (last_processed_sequence >= 0)
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
INSERT INTO saved_capsule_reverification_state (
|
|
127
|
+
singleton_id, last_processed_sequence
|
|
128
|
+
) VALUES (1, 0);
|
|
129
|
+
`);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: transactional retained-row/byte counters for the change journal.
|
|
3
|
+
*
|
|
4
|
+
* The counters let append-time retention inspect only the oldest bounded
|
|
5
|
+
* prefix that may be deleted instead of rescanning/materializing the journal.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Database } from "bun:sqlite";
|
|
9
|
+
|
|
10
|
+
import type { Migration } from "./runner";
|
|
11
|
+
|
|
12
|
+
export const migration: Migration = {
|
|
13
|
+
version: 17,
|
|
14
|
+
name: "document_change_retention_counters",
|
|
15
|
+
|
|
16
|
+
up(db: Database): void {
|
|
17
|
+
db.exec(`
|
|
18
|
+
ALTER TABLE document_change_journal_state
|
|
19
|
+
ADD COLUMN retained_entries INTEGER NOT NULL DEFAULT 0
|
|
20
|
+
CHECK (retained_entries >= 0);
|
|
21
|
+
ALTER TABLE document_change_journal_state
|
|
22
|
+
ADD COLUMN retained_bytes INTEGER NOT NULL DEFAULT 0
|
|
23
|
+
CHECK (retained_bytes >= 0);
|
|
24
|
+
|
|
25
|
+
UPDATE document_change_journal_state
|
|
26
|
+
SET retained_entries = (SELECT COUNT(*) FROM document_changes),
|
|
27
|
+
retained_bytes = (
|
|
28
|
+
SELECT COALESCE(SUM(byte_size), 0) FROM document_changes
|
|
29
|
+
)
|
|
30
|
+
WHERE singleton_id = 1;
|
|
31
|
+
`);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: saved Capsule registration epoch for race-free scheduler drains.
|
|
3
|
+
*
|
|
4
|
+
* Registration updates rewind the durable journal high-water mark and advance
|
|
5
|
+
* this epoch in the same transaction. A scheduler drain may advance the
|
|
6
|
+
* high-water mark only when no registration changed since the drain began.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Database } from "bun:sqlite";
|
|
10
|
+
|
|
11
|
+
import type { Migration } from "./runner";
|
|
12
|
+
|
|
13
|
+
export const migration: Migration = {
|
|
14
|
+
version: 18,
|
|
15
|
+
name: "saved_capsule_registration_epoch",
|
|
16
|
+
|
|
17
|
+
up(db: Database): void {
|
|
18
|
+
db.exec(`
|
|
19
|
+
ALTER TABLE saved_capsule_reverification_state
|
|
20
|
+
ADD COLUMN registration_epoch INTEGER NOT NULL DEFAULT 0
|
|
21
|
+
CHECK (registration_epoch >= 0);
|
|
22
|
+
`);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: per-registration generations for receipt persistence CAS.
|
|
3
|
+
*
|
|
4
|
+
* Existing rows receive unique generations above the durable global epoch.
|
|
5
|
+
* Future upserts allocate from that same monotonic epoch, so delete/recreate
|
|
6
|
+
* cannot reuse a verification generation even for identical Capsule bytes.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Database } from "bun:sqlite";
|
|
10
|
+
|
|
11
|
+
import type { Migration } from "./runner";
|
|
12
|
+
|
|
13
|
+
export const migration: Migration = {
|
|
14
|
+
version: 19,
|
|
15
|
+
name: "saved_capsule_registration_generation",
|
|
16
|
+
|
|
17
|
+
up(db: Database): void {
|
|
18
|
+
db.exec(`
|
|
19
|
+
ALTER TABLE saved_capsule_registrations
|
|
20
|
+
ADD COLUMN registration_generation INTEGER NOT NULL DEFAULT 0
|
|
21
|
+
CHECK (registration_generation >= 0);
|
|
22
|
+
`);
|
|
23
|
+
const currentEpoch =
|
|
24
|
+
db
|
|
25
|
+
.query<{ registration_epoch: number }, []>(
|
|
26
|
+
`SELECT registration_epoch
|
|
27
|
+
FROM saved_capsule_reverification_state
|
|
28
|
+
WHERE singleton_id = 1`
|
|
29
|
+
)
|
|
30
|
+
.get()?.registration_epoch ?? 0;
|
|
31
|
+
const rows = db
|
|
32
|
+
.query<{ registration_id: string }, []>(
|
|
33
|
+
`SELECT registration_id
|
|
34
|
+
FROM saved_capsule_registrations
|
|
35
|
+
ORDER BY registration_id ASC`
|
|
36
|
+
)
|
|
37
|
+
.all();
|
|
38
|
+
const update = db.prepare(
|
|
39
|
+
`UPDATE saved_capsule_registrations
|
|
40
|
+
SET registration_generation = ?
|
|
41
|
+
WHERE registration_id = ?`
|
|
42
|
+
);
|
|
43
|
+
for (const [index, row] of rows.entries()) {
|
|
44
|
+
update.run(currentEpoch + index + 1, row.registration_id);
|
|
45
|
+
}
|
|
46
|
+
db.run(
|
|
47
|
+
`UPDATE saved_capsule_reverification_state
|
|
48
|
+
SET registration_epoch = ?
|
|
49
|
+
WHERE singleton_id = 1`,
|
|
50
|
+
[currentEpoch + rows.length]
|
|
51
|
+
);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -28,6 +28,11 @@ import { migration as m011 } from "./011-doc-edge-traversal-indexes";
|
|
|
28
28
|
import { migration as m012 } from "./012-activation-receipts";
|
|
29
29
|
import { migration as m013 } from "./013-fts-sync-marker";
|
|
30
30
|
import { migration as m014 } from "./014-retrieval-traces";
|
|
31
|
+
import { migration as m015 } from "./015-document-change-journal";
|
|
32
|
+
import { migration as m016 } from "./016-saved-capsules";
|
|
33
|
+
import { migration as m017 } from "./017-document-change-retention-counters";
|
|
34
|
+
import { migration as m018 } from "./018-saved-capsule-registration-epoch";
|
|
35
|
+
import { migration as m019 } from "./019-saved-capsule-registration-generation";
|
|
31
36
|
|
|
32
37
|
/** All migrations in order */
|
|
33
38
|
export const migrations = [
|
|
@@ -45,4 +50,9 @@ export const migrations = [
|
|
|
45
50
|
m012,
|
|
46
51
|
m013,
|
|
47
52
|
m014,
|
|
53
|
+
m015,
|
|
54
|
+
m016,
|
|
55
|
+
m017,
|
|
56
|
+
m018,
|
|
57
|
+
m019,
|
|
48
58
|
];
|