pactium 0.2.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 (42) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +92 -0
  3. package/README.zh-CN.md +90 -0
  4. package/SECURITY.md +7 -0
  5. package/bin/pactium.mjs +121 -0
  6. package/docs/LICOLITE-ASPECT.md +57 -0
  7. package/docs/README.md +13 -0
  8. package/docs/TERM.md +289 -0
  9. package/docs/architecture/ARCHITECTURE.md +62 -0
  10. package/docs/protocols/PROFILE.md +124 -0
  11. package/docs/protocols/PROTOCOLS.md +62 -0
  12. package/examples/record-operation.mjs +26 -0
  13. package/package.json +69 -0
  14. package/src/README.md +13 -0
  15. package/src/aspects/licolite/aspect.js +278 -0
  16. package/src/aspects/licolite/constants.js +13 -0
  17. package/src/aspects/licolite/evidence.js +47 -0
  18. package/src/aspects/licolite/index.d.ts +51 -0
  19. package/src/aspects/licolite/index.js +19 -0
  20. package/src/aspects/licolite/signing.js +78 -0
  21. package/src/canonical/value.js +40 -0
  22. package/src/core/append-condition.js +102 -0
  23. package/src/core/pactium-core.js +1073 -0
  24. package/src/core/tracking-cursor.js +68 -0
  25. package/src/http.js +99 -0
  26. package/src/index-engine/snapshot-merkle-index.js +994 -0
  27. package/src/index.d.ts +244 -0
  28. package/src/index.js +73 -0
  29. package/src/ledger/signed-head.js +204 -0
  30. package/src/ledger/transparency-log.js +702 -0
  31. package/src/maintenance/task-engine.js +36 -0
  32. package/src/proof/bundle-format.js +265 -0
  33. package/src/proof/bundle.js +77 -0
  34. package/src/proof/envelope.js +548 -0
  35. package/src/proof/registry.js +18 -0
  36. package/src/protocol/constants.js +69 -0
  37. package/src/protocol/hashing.js +47 -0
  38. package/src/quality/profile-runner.js +291 -0
  39. package/src/repair/planner.js +62 -0
  40. package/src/shared/records.js +32 -0
  41. package/src/storage/local-json-storage-port.js +360 -0
  42. package/src/verification/failure.js +31 -0
@@ -0,0 +1,291 @@
1
+ import { PACTIUM_PACKAGE_VERSION, PACTIUM_PROOF_TYPES, PACTIUM_PROTOCOL } from "../protocol/constants.js";
2
+ import { protocolHash } from "../protocol/hashing.js";
3
+ import { createPactium } from "../core/pactium-core.js";
4
+ import { createVerifiableIndexEngine } from "../index-engine/snapshot-merkle-index.js";
5
+ import { verifyProofBundle } from "../proof/bundle.js";
6
+ import { createStoragePort } from "../storage/local-json-storage-port.js";
7
+
8
+ function percentile(samples, ratio, fallback) {
9
+ if (samples.length === 0) return fallback;
10
+ const sorted = [...samples].sort((left, right) => left - right);
11
+ const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * ratio) - 1));
12
+ return sorted[index];
13
+ }
14
+
15
+ function emitProgress(onProgress, event) {
16
+ if (typeof onProgress === "function") {
17
+ onProgress({
18
+ protocol: PACTIUM_PROTOCOL,
19
+ packageVersion: PACTIUM_PACKAGE_VERSION,
20
+ ...event
21
+ });
22
+ }
23
+ }
24
+
25
+ function shouldReportProgress(completed, total, interval) {
26
+ return completed === total || (interval > 0 && completed % interval === 0);
27
+ }
28
+
29
+ function shouldCompactPressure(completed, total, interval) {
30
+ return completed > 0 && (completed === total || (interval > 0 && completed % interval === 0));
31
+ }
32
+
33
+ function createPressureCore(pactium) {
34
+ if (pactium) return { core: pactium, owned: false };
35
+ const storage = createStoragePort({ inMemory: true });
36
+ return {
37
+ core: createPactium({ storage }),
38
+ storage,
39
+ owned: true
40
+ };
41
+ }
42
+
43
+ function addCompactionDetails(details, compaction) {
44
+ if (!compaction?.inMemory) return;
45
+ for (const field of ["prunedBlocks", "prunedProtocolObjects", "prunedNodes", "prunedRoots", "prunedSnapshots"]) {
46
+ details[field] = Number(details[field] || 0) + Number(compaction[field] || 0);
47
+ }
48
+ details.retainedRoots = compaction.retainedRoots;
49
+ details.retainedNodeRoots = compaction.retainedNodeRoots;
50
+ }
51
+
52
+ async function compactPressureCore(context, details) {
53
+ if (!context?.owned || typeof context.core?._compactInMemoryCaches !== "function") return;
54
+ addCompactionDetails(details, await context.core._compactInMemoryCaches());
55
+ }
56
+
57
+ export async function runPactiumQualityGateProfile({
58
+ profile = "api:index-engine",
59
+ operations = 1000,
60
+ pactium = null,
61
+ membershipProofs = Math.min(1000, operations),
62
+ nonMembershipProofs = 0,
63
+ requireDiff = false,
64
+ onProgress = null,
65
+ progressInterval = 1000,
66
+ compactionInterval = 100
67
+ } = {}) {
68
+ const started = performance.now();
69
+ const memoryStart = process.memoryUsage().rss;
70
+ const samples = [];
71
+ const details = {};
72
+ let completed = 0;
73
+ if (profile === "api:index-engine") {
74
+ const storage = createStoragePort({ inMemory: true });
75
+ const engine = createVerifiableIndexEngine({ storage, domain: "pressure" });
76
+ const entries = Array.from({ length: operations }, (_, index) => ({
77
+ key: `key:${String(index).padStart(8, "0")}`,
78
+ valueRef: `ref:${index}`,
79
+ valueHash: protocolHash("block", index)
80
+ }));
81
+ emitProgress(onProgress, { profile, phase: "create-index:start", completed: 0, total: operations });
82
+ const index = await engine.createIndex(entries);
83
+ emitProgress(onProgress, { profile, phase: "create-index:end", completed: operations, total: operations });
84
+ const membershipCount = Math.min(Number(membershipProofs || 0), operations);
85
+ for (let indexNumber = 0; indexNumber < membershipCount; indexNumber += 1) {
86
+ const operationStarted = performance.now();
87
+ const proof = await engine.prove(index.root, `key:${String(indexNumber).padStart(8, "0")}`);
88
+ if (!engine.verifyProof(proof)) throw new Error("Pressure membership proof failed.");
89
+ samples.push(performance.now() - operationStarted);
90
+ if (shouldReportProgress(indexNumber + 1, membershipCount, progressInterval)) {
91
+ emitProgress(onProgress, {
92
+ profile,
93
+ phase: "membership-proofs",
94
+ completed: indexNumber + 1,
95
+ total: membershipCount
96
+ });
97
+ }
98
+ }
99
+ const nonMembershipCount = Math.min(Number(nonMembershipProofs || 0), operations);
100
+ for (let indexNumber = 0; indexNumber < nonMembershipCount; indexNumber += 1) {
101
+ const operationStarted = performance.now();
102
+ const proof = await engine.prove(index.root, `missing:${String(indexNumber).padStart(8, "0")}`);
103
+ if (!engine.verifyProof(proof) || proof.proofType !== PACTIUM_PROOF_TYPES.indexNonMembership) {
104
+ throw new Error("Pressure non-membership proof failed.");
105
+ }
106
+ samples.push(performance.now() - operationStarted);
107
+ if (shouldReportProgress(indexNumber + 1, nonMembershipCount, progressInterval)) {
108
+ emitProgress(onProgress, {
109
+ profile,
110
+ phase: "non-membership-proofs",
111
+ completed: indexNumber + 1,
112
+ total: nonMembershipCount
113
+ });
114
+ }
115
+ }
116
+ if (requireDiff) {
117
+ emitProgress(onProgress, { profile, phase: "diff:start", completed: 0, total: 1 });
118
+ const diffStarted = performance.now();
119
+ const created = await engine.put(index.root, `key:${String(operations + 1).padStart(8, "0")}`, {
120
+ valueRef: `ref:${operations + 1}`,
121
+ valueHash: protocolHash("block", operations + 1)
122
+ });
123
+ const deletedKey = `key:${String(Math.floor(operations / 2)).padStart(8, "0")}`;
124
+ const changed = await engine.delete(created.root, deletedKey);
125
+ const changes = await engine.diff(index.root, changed.root);
126
+ samples.push(performance.now() - diffStarted);
127
+ if (!changes.some((entry) => entry.action === "create") ||
128
+ !changes.some((entry) => entry.action === "delete")) {
129
+ throw new Error("Pressure root-to-root diff failed.");
130
+ }
131
+ details.diffChanges = changes.length;
132
+ emitProgress(onProgress, { profile, phase: "diff:end", completed: 1, total: 1 });
133
+ }
134
+ details.indexKeys = operations;
135
+ details.membershipProofs = membershipCount;
136
+ details.nonMembershipProofs = nonMembershipCount;
137
+ completed = operations;
138
+ } else if (profile === "api:proof-bundle") {
139
+ const context = createPressureCore(pactium);
140
+ const { core } = context;
141
+ for (let index = 0; index < operations; index += 1) {
142
+ const operationStarted = performance.now();
143
+ const envelope = await core.recordOperation({
144
+ operationId: "pressure.bundle",
145
+ workspaceId: `workspace-${index % 10}`,
146
+ idempotencyKey: `bundle-intent-${index}`,
147
+ outcomeIdempotencyKey: `bundle-outcome-${index}`,
148
+ input: { index }
149
+ });
150
+ const bundle = await core.exportProofBundle(envelope);
151
+ const verified = await verifyProofBundle(bundle);
152
+ if (!verified.ok) throw new Error("Pressure Proof Bundle verification failed.");
153
+ samples.push(performance.now() - operationStarted);
154
+ completed += 1;
155
+ if (shouldCompactPressure(completed, operations, compactionInterval)) {
156
+ await compactPressureCore(context, details);
157
+ }
158
+ if (shouldReportProgress(completed, operations, progressInterval)) {
159
+ emitProgress(onProgress, { profile, phase: "operations", completed, total: operations });
160
+ }
161
+ }
162
+ } else if (profile === "api:recovery") {
163
+ const context = createPressureCore(pactium);
164
+ const { core } = context;
165
+ const intents = [];
166
+ const workspaceCounts = new Map();
167
+ const intentWorkspaces = new Map();
168
+ const sampleOutcomes = [];
169
+ for (let index = 0; index < operations; index += 1) {
170
+ const workspaceId = `workspace-${index % 10}`;
171
+ workspaceCounts.set(workspaceId, (workspaceCounts.get(workspaceId) || 0) + 1);
172
+ const intent = await core.beginOperationIntent({
173
+ operationId: "pressure.recovery",
174
+ workspaceId,
175
+ idempotencyKey: `recovery-intent-${index}`,
176
+ input: { index }
177
+ });
178
+ intentWorkspaces.set(intent.factId, workspaceId);
179
+ intents.push(intent);
180
+ if (shouldCompactPressure(index + 1, operations, compactionInterval)) {
181
+ await compactPressureCore(context, details);
182
+ }
183
+ if (shouldReportProgress(index + 1, operations, progressInterval)) {
184
+ emitProgress(onProgress, { profile, phase: "open-intents", completed: index + 1, total: operations });
185
+ }
186
+ }
187
+ for (const [index, intent] of intents.entries()) {
188
+ const operationStarted = performance.now();
189
+ const outcome = await core.appendOperationOutcome({
190
+ intentId: intent.factId,
191
+ outcomeIdempotencyKey: `recovery-outcome-${index}`,
192
+ status: "recovered"
193
+ });
194
+ const lookup = await core.lookupOutcome(intent.factId);
195
+ if (!lookup.exists) throw new Error("Pressure recovery outcome lookup failed.");
196
+ if (sampleOutcomes.length < 10) {
197
+ sampleOutcomes.push({
198
+ workspaceId: intentWorkspaces.get(intent.factId) || "default",
199
+ ledgerEventId: outcome.factRef.ledgerEventId
200
+ });
201
+ }
202
+ samples.push(performance.now() - operationStarted);
203
+ completed += 1;
204
+ if (shouldCompactPressure(completed, operations, compactionInterval)) {
205
+ await compactPressureCore(context, details);
206
+ }
207
+ if (shouldReportProgress(completed, operations, progressInterval)) {
208
+ emitProgress(onProgress, { profile, phase: "recovered-outcomes", completed, total: operations });
209
+ }
210
+ }
211
+ for (const [workspaceId, count] of workspaceCounts) {
212
+ const projection = await core.getWorkspaceProjection(workspaceId);
213
+ if (projection.nextOrdinal !== count * 2) {
214
+ throw new Error("Pressure recovery workspace projection consistency failed.");
215
+ }
216
+ }
217
+ for (const outcome of sampleOutcomes) {
218
+ const membership = await core.proveWorkspaceMembership({
219
+ workspaceId: outcome.workspaceId,
220
+ ledgerEventId: outcome.ledgerEventId
221
+ });
222
+ if (!membership.member || !core.indexEngine.verifyProof(membership.proof)) {
223
+ throw new Error("Pressure recovery workspace membership proof failed.");
224
+ }
225
+ }
226
+ } else if (profile === "api:licolite-record") {
227
+ const { createLicoLiteAspect } = await import("../aspects/licolite/index.js");
228
+ const context = createPressureCore(pactium);
229
+ const { core } = context;
230
+ const aspect = createLicoLiteAspect({ pactium: core, evidencePolicy: "production" });
231
+ for (let index = 0; index < operations; index += 1) {
232
+ const operationStarted = performance.now();
233
+ const envelope = await aspect.recordWorkspaceOperation({
234
+ operationId: "pressure.licolite",
235
+ workspaceId: `workspace-${index % 10}`,
236
+ idempotencyKey: `licolite-intent-${index}`,
237
+ outcomeIdempotencyKey: `licolite-outcome-${index}`,
238
+ input: { index },
239
+ policyEvidence: { decision: "allow", index },
240
+ workspaceEffectEvidence: { effect: "record", index }
241
+ });
242
+ const verified = await aspect.verifyEnvelope(envelope);
243
+ if (!verified.ok) throw new Error("Pressure LicoLite verification failed.");
244
+ samples.push(performance.now() - operationStarted);
245
+ completed += 1;
246
+ if (shouldCompactPressure(completed, operations, compactionInterval)) {
247
+ await compactPressureCore(context, details);
248
+ }
249
+ if (shouldReportProgress(completed, operations, progressInterval)) {
250
+ emitProgress(onProgress, { profile, phase: "operations", completed, total: operations });
251
+ }
252
+ }
253
+ } else {
254
+ const context = createPressureCore(pactium);
255
+ const { core } = context;
256
+ for (let index = 0; index < operations; index += 1) {
257
+ const operationStarted = performance.now();
258
+ await core.recordOperation({
259
+ operationId: `${profile}.operation`,
260
+ workspaceId: `workspace-${index % 10}`,
261
+ idempotencyKey: `intent-${index}`,
262
+ outcomeIdempotencyKey: `outcome-${index}`,
263
+ input: { index }
264
+ });
265
+ samples.push(performance.now() - operationStarted);
266
+ completed += 1;
267
+ if (shouldCompactPressure(completed, operations, compactionInterval)) {
268
+ await compactPressureCore(context, details);
269
+ }
270
+ if (shouldReportProgress(completed, operations, progressInterval)) {
271
+ emitProgress(onProgress, { profile, phase: "operations", completed, total: operations });
272
+ }
273
+ }
274
+ }
275
+ const durationMs = Math.max(1, performance.now() - started);
276
+ const memoryHighWaterMark = Math.max(memoryStart, process.memoryUsage().rss);
277
+ const averageMs = durationMs / Math.max(1, completed);
278
+ return {
279
+ protocol: PACTIUM_PROTOCOL,
280
+ packageVersion: PACTIUM_PACKAGE_VERSION,
281
+ profile,
282
+ operationCount: completed,
283
+ durationMs,
284
+ throughputPerSecond: completed / (durationMs / 1000),
285
+ p50Ms: percentile(samples, 0.5, averageMs),
286
+ p95Ms: percentile(samples, 0.95, averageMs),
287
+ p99Ms: percentile(samples, 0.99, averageMs),
288
+ memoryHighWaterMark,
289
+ details
290
+ };
291
+ }
@@ -0,0 +1,62 @@
1
+ import { PACTIUM_PROTOCOL } from "../protocol/constants.js";
2
+ import { createId } from "../protocol/hashing.js";
3
+ import { asArray } from "../shared/records.js";
4
+
5
+ export function createRepairPlanner() {
6
+ function actionForFailure(failure) {
7
+ const code = String(failure.code || "");
8
+ const layer = String(failure.layer || "");
9
+ if (code.includes("open_intent") || code.includes("intent_missing")) return "resume-open-intent";
10
+ if (code.includes("missing_proof") || code.includes("missing_bundle") || code.includes("missing_extension")) return "restore-missing-proof-material";
11
+ if (code.includes("host_evidence") || code.includes("licolite") || code.includes("evidence")) return "request-host-evidence";
12
+ if (code.includes("conflict") || code.includes("terminal_outcome")) return "manual-conflict-resolution";
13
+ if (layer.includes("workspace") || code.includes("workspace") || code.includes("derived") || code.includes("consistency")) return "rebuild-derived-index";
14
+ if (code.includes("unsupported_critical")) return "install-verifier-support";
15
+ return "manual-investigation";
16
+ }
17
+
18
+ function plan(failures = []) {
19
+ return {
20
+ protocol: PACTIUM_PROTOCOL,
21
+ planner: "pactium.v0.2.repair-planner",
22
+ tasks: asArray(failures).map((failure, index) => {
23
+ const action = actionForFailure(failure);
24
+ return {
25
+ taskId: createId("repair_task", { index, failure }),
26
+ action,
27
+ layer: failure.layer || "unknown",
28
+ evidenceRef: failure.evidenceRef || "",
29
+ deterministic: true,
30
+ inventsFacts: false,
31
+ recordsRepairFact: false
32
+ };
33
+ })
34
+ };
35
+ }
36
+
37
+ function planRecovery({ cursor = null, failures = [], lifecycleState = {} } = {}) {
38
+ const base = plan(failures);
39
+ const tasks = [...base.tasks];
40
+ if (cursor && cursor.scope) {
41
+ tasks.push({
42
+ taskId: createId("repair_task", { cursor, lifecycleState, kind: "cursor-recovery" }),
43
+ action: "resume-open-intent",
44
+ layer: "recovery",
45
+ evidenceRef: cursor.cursorId || "",
46
+ deterministic: true,
47
+ inventsFacts: false,
48
+ recordsRepairFact: false,
49
+ cursor
50
+ });
51
+ }
52
+ return {
53
+ ...base,
54
+ recoveryPlanType: "pactium.recovery-plan",
55
+ cursor,
56
+ lifecycleState,
57
+ tasks
58
+ };
59
+ }
60
+
61
+ return Object.freeze({ protocol: PACTIUM_PROTOCOL, plan, planRecovery });
62
+ }
@@ -0,0 +1,32 @@
1
+ export function nowIso() {
2
+ return new Date().toISOString();
3
+ }
4
+
5
+ /* node:coverage disable */
6
+ export function asRecord(value) {
7
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
8
+ }
9
+
10
+ export function asArray(value) {
11
+ return Array.isArray(value) ? value : [];
12
+ }
13
+
14
+ export function compactObject(value) {
15
+ return Object.fromEntries(
16
+ Object.entries(value).filter(([, nested]) => nested !== undefined)
17
+ );
18
+ }
19
+
20
+ export function safeText(value, fallback = "") {
21
+ const output = String(value ?? "").trim();
22
+ return output || fallback;
23
+ }
24
+
25
+ export function safeToken(value, fallback = "default") {
26
+ return String(value || fallback)
27
+ .trim()
28
+ .replace(/[^a-zA-Z0-9._:-]+/g, "_")
29
+ .replace(/^_+|_+$/g, "")
30
+ .slice(0, 180) || fallback;
31
+ }
32
+ /* node:coverage enable */