@feltdb/core 0.4.17 → 0.5.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 +169 -0
- package/dist/cli/index.js +1 -1
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/Cargo.lock +12 -0
- package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -0
- package/dist/create/server-source/crates/feltdb-server/src/lib.rs +2 -0
- package/dist/create/server-source/crates/feltdb-server/src/request_telemetry.rs +381 -0
- package/dist/create/server-source/crates/feltdb-server/src/transaction_idempotency.rs +280 -0
- package/dist/error-codes.d.ts +53 -0
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +46 -0
- package/dist/feltdb.d.ts +4 -0
- package/dist/feltdb.d.ts.map +1 -1
- package/dist/file-db.d.ts +3 -0
- package/dist/file-db.d.ts.map +1 -1
- package/dist/file-db.js +130 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/operation-admission.d.ts +141 -0
- package/dist/operation-admission.d.ts.map +1 -0
- package/dist/operation-admission.js +135 -0
- package/dist/revision-recovery.d.ts +162 -0
- package/dist/revision-recovery.d.ts.map +1 -0
- package/dist/revision-recovery.js +69 -0
- package/dist/state-contract.d.ts +2 -0
- package/dist/state-contract.d.ts.map +1 -1
- package/dist/state-contract.js +17 -7
- package/dist/studio-app/assets/{index-5siPkRSN.js → index-3cvTQ0Mv.js} +10 -10
- package/dist/studio-app/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic Idempotent Operation Admission
|
|
3
|
+
*
|
|
4
|
+
* Defines the durable operation admission contract for FeltDB.
|
|
5
|
+
* Guarantees: exactly one operation identity per idempotency key,
|
|
6
|
+
* atomic durability, and convergence across concurrent callers.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Input contract for admitting a durable operation
|
|
10
|
+
*/
|
|
11
|
+
export interface OperationAdmissionInput {
|
|
12
|
+
/** Unique idempotency key supplied by caller */
|
|
13
|
+
idempotencyKey: string;
|
|
14
|
+
/** Operation kind (e.g., "execution", "coordination", "verification") */
|
|
15
|
+
kind: string;
|
|
16
|
+
/** Optional immutable operation fingerprint for conflict detection */
|
|
17
|
+
operationFingerprint?: string;
|
|
18
|
+
/** Caller-supplied metadata */
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Operation lifecycle status
|
|
23
|
+
*/
|
|
24
|
+
export type OperationStatus = 'accepted' | 'executing' | 'completed' | 'failed' | 'cancelled';
|
|
25
|
+
/**
|
|
26
|
+
* Durable operation record with versioned lifecycle
|
|
27
|
+
*/
|
|
28
|
+
export interface DurableOperation {
|
|
29
|
+
/** FeltDB-generated operation identity (ULIDv7 or similar) */
|
|
30
|
+
operationId: string;
|
|
31
|
+
/** Caller's idempotency key */
|
|
32
|
+
idempotencyKey: string;
|
|
33
|
+
/** Operation kind (immutable) */
|
|
34
|
+
kind: string;
|
|
35
|
+
/** Current operation status in lifecycle */
|
|
36
|
+
status: OperationStatus;
|
|
37
|
+
/** Version number (increments by 1 on each successful transition) */
|
|
38
|
+
version: number;
|
|
39
|
+
/** Timestamp when operation was admitted */
|
|
40
|
+
createdAt: number;
|
|
41
|
+
/** Timestamp when execution started */
|
|
42
|
+
startedAt?: number;
|
|
43
|
+
/** Timestamp when operation terminal state reached */
|
|
44
|
+
completedAt?: number;
|
|
45
|
+
/** Operation fingerprint for conflict detection */
|
|
46
|
+
operationFingerprint?: string;
|
|
47
|
+
/** Caller metadata */
|
|
48
|
+
metadata?: Record<string, unknown>;
|
|
49
|
+
/** Result/outcome for terminal states */
|
|
50
|
+
resultSnapshot?: unknown;
|
|
51
|
+
/** Error message for failed operations */
|
|
52
|
+
error?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Result of an operation admission attempt
|
|
56
|
+
*/
|
|
57
|
+
export interface OperationAdmissionResult {
|
|
58
|
+
/** True if this caller admitted the operation; false if it already existed */
|
|
59
|
+
admitted: boolean;
|
|
60
|
+
/** FeltDB-generated operation identity (same for all callers with same idempotencyKey) */
|
|
61
|
+
operationId: string;
|
|
62
|
+
/** The durable operation record */
|
|
63
|
+
operation: DurableOperation;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Conflict error when idempotency key is reused with different operation semantics
|
|
67
|
+
*/
|
|
68
|
+
export interface IdempotencyConflictError {
|
|
69
|
+
code: 'IDEMPOTENCY_CONFLICT';
|
|
70
|
+
idempotencyKey: string;
|
|
71
|
+
existingKind: string;
|
|
72
|
+
requestedKind: string;
|
|
73
|
+
existingFingerprint?: string;
|
|
74
|
+
requestedFingerprint?: string;
|
|
75
|
+
message: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Input for atomic operation lifecycle transition
|
|
79
|
+
*/
|
|
80
|
+
export interface OperationTransitionInput {
|
|
81
|
+
/** Operation ID to transition */
|
|
82
|
+
operationId: string;
|
|
83
|
+
/** Expected current version (for CAS) */
|
|
84
|
+
expectedVersion: number;
|
|
85
|
+
/** Target status after transition */
|
|
86
|
+
to: OperationStatus;
|
|
87
|
+
/** Result data for terminal states */
|
|
88
|
+
resultSnapshot?: unknown;
|
|
89
|
+
/** Error message for failed operations */
|
|
90
|
+
error?: string;
|
|
91
|
+
/** Metadata for the transition event */
|
|
92
|
+
metadata?: Record<string, unknown>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Result of a transition attempt
|
|
96
|
+
*/
|
|
97
|
+
export interface OperationTransitionResult {
|
|
98
|
+
/** True if transition succeeded */
|
|
99
|
+
transitioned: boolean;
|
|
100
|
+
/** Reason for failure (if transitioned = false) */
|
|
101
|
+
reason?: 'VERSION_CONFLICT' | 'INVALID_TRANSITION' | 'NOT_FOUND';
|
|
102
|
+
/** Current operation state (after transition or at rejection) */
|
|
103
|
+
operation: DurableOperation;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Validates operation admission inputs
|
|
107
|
+
*/
|
|
108
|
+
export declare function validateOperationAdmissionInput(input: OperationAdmissionInput): {
|
|
109
|
+
valid: boolean;
|
|
110
|
+
error?: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Checks if two operations conflict based on immutable semantics
|
|
114
|
+
*/
|
|
115
|
+
export declare function operationsConflict(existing: DurableOperation, requested: OperationAdmissionInput): IdempotencyConflictError | null;
|
|
116
|
+
/**
|
|
117
|
+
* Generates a stable operation ID
|
|
118
|
+
* In production, use ULIDv7 for sortability and distributed uniqueness
|
|
119
|
+
*/
|
|
120
|
+
export declare function generateOperationId(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Validates that a transition is legal according to the state machine
|
|
123
|
+
*/
|
|
124
|
+
export declare function isValidTransition(fromStatus: OperationStatus, toStatus: OperationStatus): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Checks if a status is a terminal state
|
|
127
|
+
*/
|
|
128
|
+
export declare function isTerminalStatus(status: OperationStatus): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Validates transition input
|
|
131
|
+
*/
|
|
132
|
+
export declare function validateTransitionInput(input: OperationTransitionInput): {
|
|
133
|
+
valid: boolean;
|
|
134
|
+
error?: string;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Checks if a terminal transition is idempotent
|
|
138
|
+
* (same result data means it's the same transition, not a new one)
|
|
139
|
+
*/
|
|
140
|
+
export declare function isIdempotentTerminalTransition(existingOp: DurableOperation, requestedResult?: unknown, requestedError?: string): boolean;
|
|
141
|
+
//# sourceMappingURL=operation-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-admission.d.ts","sourceRoot":"","sources":["../src/operation-admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic Idempotent Operation Admission
|
|
3
|
+
*
|
|
4
|
+
* Defines the durable operation admission contract for FeltDB.
|
|
5
|
+
* Guarantees: exactly one operation identity per idempotency key,
|
|
6
|
+
* atomic durability, and convergence across concurrent callers.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Validates operation admission inputs
|
|
10
|
+
*/
|
|
11
|
+
export function validateOperationAdmissionInput(input) {
|
|
12
|
+
if (!input.idempotencyKey || typeof input.idempotencyKey !== 'string') {
|
|
13
|
+
return { valid: false, error: 'idempotencyKey must be a non-empty string' };
|
|
14
|
+
}
|
|
15
|
+
if (!input.kind || typeof input.kind !== 'string') {
|
|
16
|
+
return { valid: false, error: 'kind must be a non-empty string' };
|
|
17
|
+
}
|
|
18
|
+
if (input.idempotencyKey.length > 255) {
|
|
19
|
+
return { valid: false, error: 'idempotencyKey must be <= 255 characters' };
|
|
20
|
+
}
|
|
21
|
+
if (input.kind.length > 64) {
|
|
22
|
+
return { valid: false, error: 'kind must be <= 64 characters' };
|
|
23
|
+
}
|
|
24
|
+
if (input.operationFingerprint && input.operationFingerprint.length > 255) {
|
|
25
|
+
return { valid: false, error: 'operationFingerprint must be <= 255 characters' };
|
|
26
|
+
}
|
|
27
|
+
return { valid: true };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Checks if two operations conflict based on immutable semantics
|
|
31
|
+
*/
|
|
32
|
+
export function operationsConflict(existing, requested) {
|
|
33
|
+
// Same idempotencyKey must have same kind
|
|
34
|
+
if (existing.kind !== requested.kind) {
|
|
35
|
+
return {
|
|
36
|
+
code: 'IDEMPOTENCY_CONFLICT',
|
|
37
|
+
idempotencyKey: existing.idempotencyKey,
|
|
38
|
+
existingKind: existing.kind,
|
|
39
|
+
requestedKind: requested.kind,
|
|
40
|
+
message: `Operation kind mismatch for idempotencyKey "${existing.idempotencyKey}": existing="${existing.kind}", requested="${requested.kind}"`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// If fingerprint is supplied, it must match
|
|
44
|
+
if (requested.operationFingerprint) {
|
|
45
|
+
if (existing.operationFingerprint !== requested.operationFingerprint) {
|
|
46
|
+
return {
|
|
47
|
+
code: 'IDEMPOTENCY_CONFLICT',
|
|
48
|
+
idempotencyKey: existing.idempotencyKey,
|
|
49
|
+
existingKind: existing.kind,
|
|
50
|
+
requestedKind: requested.kind,
|
|
51
|
+
existingFingerprint: existing.operationFingerprint,
|
|
52
|
+
requestedFingerprint: requested.operationFingerprint,
|
|
53
|
+
message: `Operation fingerprint mismatch for idempotencyKey "${existing.idempotencyKey}": existing="${existing.operationFingerprint}", requested="${requested.operationFingerprint}"`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generates a stable operation ID
|
|
61
|
+
* In production, use ULIDv7 for sortability and distributed uniqueness
|
|
62
|
+
*/
|
|
63
|
+
export function generateOperationId() {
|
|
64
|
+
// Format: timestamp (13 bytes) + random (12 bytes) = 25 chars
|
|
65
|
+
// For now, use a simple format; consider switching to proper ULID
|
|
66
|
+
const timestamp = Date.now();
|
|
67
|
+
const random = Math.random().toString(36).substring(2, 15) +
|
|
68
|
+
Math.random().toString(36).substring(2, 15);
|
|
69
|
+
return `op-${timestamp}-${random}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Legal state transitions in the operation lifecycle
|
|
73
|
+
*
|
|
74
|
+
* Invariant: Each successful transition increments version by exactly 1.
|
|
75
|
+
* Terminal states (completed, failed, cancelled) have no outgoing transitions.
|
|
76
|
+
*/
|
|
77
|
+
const LEGAL_TRANSITIONS = {
|
|
78
|
+
accepted: ['executing', 'cancelled'],
|
|
79
|
+
executing: ['completed', 'failed', 'cancelled'],
|
|
80
|
+
completed: [], // Terminal: no transitions allowed
|
|
81
|
+
failed: [], // Terminal: no transitions allowed
|
|
82
|
+
cancelled: [], // Terminal: no transitions allowed
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Validates that a transition is legal according to the state machine
|
|
86
|
+
*/
|
|
87
|
+
export function isValidTransition(fromStatus, toStatus) {
|
|
88
|
+
const allowedTargets = LEGAL_TRANSITIONS[fromStatus] || [];
|
|
89
|
+
return allowedTargets.includes(toStatus);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Checks if a status is a terminal state
|
|
93
|
+
*/
|
|
94
|
+
export function isTerminalStatus(status) {
|
|
95
|
+
return ['completed', 'failed', 'cancelled'].includes(status);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validates transition input
|
|
99
|
+
*/
|
|
100
|
+
export function validateTransitionInput(input) {
|
|
101
|
+
if (!input.operationId || typeof input.operationId !== 'string') {
|
|
102
|
+
return { valid: false, error: 'operationId must be a non-empty string' };
|
|
103
|
+
}
|
|
104
|
+
if (typeof input.expectedVersion !== 'number' || input.expectedVersion < 0) {
|
|
105
|
+
return { valid: false, error: 'expectedVersion must be a non-negative number' };
|
|
106
|
+
}
|
|
107
|
+
if (!input.to || typeof input.to !== 'string') {
|
|
108
|
+
return { valid: false, error: 'to must specify a target status' };
|
|
109
|
+
}
|
|
110
|
+
const validStatuses = ['accepted', 'executing', 'completed', 'failed', 'cancelled'];
|
|
111
|
+
if (!validStatuses.includes(input.to)) {
|
|
112
|
+
return { valid: false, error: `to must be one of: ${validStatuses.join(', ')}` };
|
|
113
|
+
}
|
|
114
|
+
return { valid: true };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Checks if a terminal transition is idempotent
|
|
118
|
+
* (same result data means it's the same transition, not a new one)
|
|
119
|
+
*/
|
|
120
|
+
export function isIdempotentTerminalTransition(existingOp, requestedResult, requestedError) {
|
|
121
|
+
// If operation is already in terminal state
|
|
122
|
+
if (!isTerminalStatus(existingOp.status)) {
|
|
123
|
+
return false; // Not a terminal op
|
|
124
|
+
}
|
|
125
|
+
// For completed operations, check result
|
|
126
|
+
if (existingOp.status === 'completed') {
|
|
127
|
+
return JSON.stringify(existingOp.resultSnapshot) === JSON.stringify(requestedResult);
|
|
128
|
+
}
|
|
129
|
+
// For failed operations, check error message
|
|
130
|
+
if (existingOp.status === 'failed') {
|
|
131
|
+
return existingOp.error === requestedError;
|
|
132
|
+
}
|
|
133
|
+
// For cancelled operations, idempotent
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revision Recovery: Audited Recovery from Invalid Historical Revisions
|
|
3
|
+
*
|
|
4
|
+
* Provides mechanisms to safely recover from corrupt/invalid historical revisions
|
|
5
|
+
* under strict safety constraints and comprehensive audit trail requirements.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Authorization level required for revision recovery operations
|
|
9
|
+
*/
|
|
10
|
+
export type RecoveryAuthorization = 'ELEVATED' | 'ADMIN' | 'EMERGENCY';
|
|
11
|
+
/**
|
|
12
|
+
* Compatibility classification for manifest changes
|
|
13
|
+
*/
|
|
14
|
+
export type CompatibilityClassification = 'COMPATIBLE' | 'WARNING' | 'INCOMPATIBLE';
|
|
15
|
+
/**
|
|
16
|
+
* Recovery mode indicating what was approved
|
|
17
|
+
*/
|
|
18
|
+
export type RecoveryMode = 'SAFE_COMPATIBLE' | 'WARNING_APPROVED' | 'DESTRUCTIVE_APPROVED';
|
|
19
|
+
/**
|
|
20
|
+
* Input for recovering an application revision
|
|
21
|
+
*/
|
|
22
|
+
export interface RevisionRecoveryInput {
|
|
23
|
+
/** Application ID being recovered */
|
|
24
|
+
applicationId: string;
|
|
25
|
+
/** Current revision that is invalid/corrupt (must match actual current) */
|
|
26
|
+
expectedCurrentRevision: string;
|
|
27
|
+
/** Target revision to promote to (must be valid and integrity-checked) */
|
|
28
|
+
targetRevision: string;
|
|
29
|
+
/** Elevated authorization level required */
|
|
30
|
+
authorization: RecoveryAuthorization;
|
|
31
|
+
/** Actor (user/service) approving recovery */
|
|
32
|
+
actor: string;
|
|
33
|
+
/** Explicit reason for recovery */
|
|
34
|
+
reason: string;
|
|
35
|
+
/** Environment being recovered */
|
|
36
|
+
environment?: string;
|
|
37
|
+
/** Allow destructive schema changes if compatibility check requires it */
|
|
38
|
+
allowDestructiveChange?: boolean;
|
|
39
|
+
/** Explicit reason for approving destructive changes (required if allowDestructiveChange=true) */
|
|
40
|
+
destructiveChangeReason?: string;
|
|
41
|
+
/** Idempotency key for recovery operation */
|
|
42
|
+
recoveryId?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Audit record for a completed revision recovery
|
|
46
|
+
*/
|
|
47
|
+
export interface RevisionRecoveryAudit {
|
|
48
|
+
/** Unique audit record ID */
|
|
49
|
+
auditId: string;
|
|
50
|
+
/** Application being recovered */
|
|
51
|
+
applicationId: string;
|
|
52
|
+
/** Source (corrupt) revision being abandoned */
|
|
53
|
+
sourceRevision: string;
|
|
54
|
+
/** Recomputed hash of source revision (for verification) */
|
|
55
|
+
sourceRevisionHash: string;
|
|
56
|
+
/** Target revision being promoted to */
|
|
57
|
+
targetRevision: string;
|
|
58
|
+
/** Hash of target revision */
|
|
59
|
+
targetRevisionHash: string;
|
|
60
|
+
/** Hash of previous audit record in chain (for immutability) */
|
|
61
|
+
previousAuditHash?: string;
|
|
62
|
+
/** Hash of this audit record */
|
|
63
|
+
auditHash: string;
|
|
64
|
+
/** Actor who approved recovery */
|
|
65
|
+
approvedBy: string;
|
|
66
|
+
/** Recovery reason provided */
|
|
67
|
+
reason: string;
|
|
68
|
+
/** Authorization level that was required */
|
|
69
|
+
authorizationLevel: RecoveryAuthorization;
|
|
70
|
+
/** Mode of recovery (what was approved) */
|
|
71
|
+
recoveryMode: RecoveryMode;
|
|
72
|
+
/** Compatibility classification from diff analysis */
|
|
73
|
+
compatibilityClassification: CompatibilityClassification;
|
|
74
|
+
/** Detailed compatibility issues found (if any) */
|
|
75
|
+
compatibilityIssues?: string[];
|
|
76
|
+
/** Destructive change approval reason (if applicable) */
|
|
77
|
+
destructiveChangeReason?: string;
|
|
78
|
+
/** Timestamp of recovery */
|
|
79
|
+
recoveredAt: number;
|
|
80
|
+
/** Idempotency key for the recovery operation */
|
|
81
|
+
recoveryId: string;
|
|
82
|
+
/** Status of recovery operation */
|
|
83
|
+
status: 'COMPLETED' | 'PARTIAL' | 'ROLLED_BACK';
|
|
84
|
+
/** Marker indicating source revision must never be moved back to */
|
|
85
|
+
markedUntrustedUntilRevision: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Result of a revision recovery attempt
|
|
89
|
+
*/
|
|
90
|
+
export interface RevisionRecoveryResult {
|
|
91
|
+
/** Whether recovery succeeded */
|
|
92
|
+
success: boolean;
|
|
93
|
+
/** Error code if recovery failed */
|
|
94
|
+
errorCode?: 'PERMISSION_DENIED' | 'CONFLICT' | 'INCOMPATIBLE_SCHEMA' | 'CORRUPT_REVISION_UNMOVABLE' | 'STORAGE_FAILURE' | 'VALIDATION_FAILED';
|
|
95
|
+
/** Human-readable error message */
|
|
96
|
+
errorMessage?: string;
|
|
97
|
+
/** Audit record created (present if recovery succeeds or partially completes) */
|
|
98
|
+
audit?: RevisionRecoveryAudit;
|
|
99
|
+
/** Current revision pointer after recovery attempt */
|
|
100
|
+
currentRevision: string;
|
|
101
|
+
/** Whether audit record was durable persisted */
|
|
102
|
+
auditDurable: boolean;
|
|
103
|
+
/** Pointer was successfully moved to target */
|
|
104
|
+
pointerMoved: boolean;
|
|
105
|
+
/** Source revision was marked untrusted */
|
|
106
|
+
sourceMarkedUntrusted: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Revision state tracking for corrupt/untrusted revisions
|
|
110
|
+
*/
|
|
111
|
+
export interface RevisionState {
|
|
112
|
+
/** Revision ID */
|
|
113
|
+
revisionId: string;
|
|
114
|
+
/** Whether revision is valid/trusted */
|
|
115
|
+
trusted: boolean;
|
|
116
|
+
/** Marker: any revision equal to or before this cannot be promoted to */
|
|
117
|
+
untrustedUntilRevision?: string;
|
|
118
|
+
/** Reason revision was marked untrusted (if applicable) */
|
|
119
|
+
untrustedReason?: string;
|
|
120
|
+
/** Timestamp when marked untrusted */
|
|
121
|
+
markedUntrustedAt?: number;
|
|
122
|
+
/** Reference to recovery audit that marked it untrusted */
|
|
123
|
+
recoveryAuditId?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Compatibility check result
|
|
127
|
+
*/
|
|
128
|
+
export interface CompatibilityCheckResult {
|
|
129
|
+
/** Overall compatibility classification */
|
|
130
|
+
classification: CompatibilityClassification;
|
|
131
|
+
/** List of specific issues or warnings found */
|
|
132
|
+
issues: Array<{
|
|
133
|
+
category: 'SCHEMA_CHANGE' | 'DATA_LOSS' | 'REFERENCE_BREAKING' | 'INDEX_REMOVAL';
|
|
134
|
+
severity: 'WARNING' | 'INCOMPATIBLE';
|
|
135
|
+
detail: string;
|
|
136
|
+
}>;
|
|
137
|
+
/** Whether any data loss would occur */
|
|
138
|
+
causesDataLoss: boolean;
|
|
139
|
+
/** Whether this is a breaking change */
|
|
140
|
+
isBreakingChange: boolean;
|
|
141
|
+
/** Recommended action */
|
|
142
|
+
recommendation: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Validates revision recovery input
|
|
146
|
+
*/
|
|
147
|
+
export declare function validateRevisionRecoveryInput(input: RevisionRecoveryInput): {
|
|
148
|
+
valid: boolean;
|
|
149
|
+
error?: string;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Generates cryptographic hash for audit record chain
|
|
153
|
+
*/
|
|
154
|
+
export declare function generateAuditHash(data: Record<string, unknown>, previousHash?: string): string;
|
|
155
|
+
/**
|
|
156
|
+
* Checks if a revision pointer transition would violate untrust markers
|
|
157
|
+
*/
|
|
158
|
+
export declare function wouldViolateUntrustworthiness(fromRevision: string, toRevision: string, revisionStates: Map<string, RevisionState>): {
|
|
159
|
+
violates: boolean;
|
|
160
|
+
reason?: string;
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=revision-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-recovery.d.ts","sourceRoot":"","sources":["../src/revision-recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revision Recovery: Audited Recovery from Invalid Historical Revisions
|
|
3
|
+
*
|
|
4
|
+
* Provides mechanisms to safely recover from corrupt/invalid historical revisions
|
|
5
|
+
* under strict safety constraints and comprehensive audit trail requirements.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates revision recovery input
|
|
9
|
+
*/
|
|
10
|
+
export function validateRevisionRecoveryInput(input) {
|
|
11
|
+
if (!input.applicationId || typeof input.applicationId !== 'string') {
|
|
12
|
+
return { valid: false, error: 'applicationId must be a non-empty string' };
|
|
13
|
+
}
|
|
14
|
+
if (!input.expectedCurrentRevision || typeof input.expectedCurrentRevision !== 'string') {
|
|
15
|
+
return { valid: false, error: 'expectedCurrentRevision must be a non-empty string' };
|
|
16
|
+
}
|
|
17
|
+
if (!input.targetRevision || typeof input.targetRevision !== 'string') {
|
|
18
|
+
return { valid: false, error: 'targetRevision must be a non-empty string' };
|
|
19
|
+
}
|
|
20
|
+
if (!input.authorization || !['ELEVATED', 'ADMIN', 'EMERGENCY'].includes(input.authorization)) {
|
|
21
|
+
return { valid: false, error: 'authorization must be ELEVATED, ADMIN, or EMERGENCY' };
|
|
22
|
+
}
|
|
23
|
+
if (!input.actor || typeof input.actor !== 'string') {
|
|
24
|
+
return { valid: false, error: 'actor must be a non-empty string' };
|
|
25
|
+
}
|
|
26
|
+
if (!input.reason || typeof input.reason !== 'string' || input.reason.length < 10) {
|
|
27
|
+
return { valid: false, error: 'reason must be a string with at least 10 characters' };
|
|
28
|
+
}
|
|
29
|
+
if (input.expectedCurrentRevision === input.targetRevision) {
|
|
30
|
+
return { valid: false, error: 'expectedCurrentRevision and targetRevision must be different' };
|
|
31
|
+
}
|
|
32
|
+
if (input.allowDestructiveChange === true) {
|
|
33
|
+
if (!input.destructiveChangeReason || typeof input.destructiveChangeReason !== 'string' || input.destructiveChangeReason.length < 10) {
|
|
34
|
+
return { valid: false, error: 'destructiveChangeReason must be provided and at least 10 characters when allowDestructiveChange=true' };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { valid: true };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Generates cryptographic hash for audit record chain
|
|
41
|
+
*/
|
|
42
|
+
export function generateAuditHash(data, previousHash) {
|
|
43
|
+
// In production, use SHA-256 or similar
|
|
44
|
+
// For now, use a simple hash based on JSON serialization
|
|
45
|
+
const payload = JSON.stringify({ ...data, previousHash });
|
|
46
|
+
// Use Buffer for Node.js, or btoa for browser environments
|
|
47
|
+
const encoded = typeof btoa !== 'undefined'
|
|
48
|
+
? btoa(payload)
|
|
49
|
+
: Buffer.from(payload).toString('base64');
|
|
50
|
+
return encoded.substring(0, 64);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a revision pointer transition would violate untrust markers
|
|
54
|
+
*/
|
|
55
|
+
export function wouldViolateUntrustworthiness(fromRevision, toRevision, revisionStates) {
|
|
56
|
+
const state = revisionStates.get(fromRevision);
|
|
57
|
+
if (!state || !state.untrustedUntilRevision) {
|
|
58
|
+
return { violates: false };
|
|
59
|
+
}
|
|
60
|
+
// Check if trying to move back to or through an untrusted revision
|
|
61
|
+
// This is a simplified check; production would need proper revision ordering
|
|
62
|
+
if (toRevision === state.untrustedUntilRevision || state.untrustedUntilRevision === fromRevision) {
|
|
63
|
+
return {
|
|
64
|
+
violates: true,
|
|
65
|
+
reason: `Revision ${fromRevision} is marked untrusted and cannot be moved back to`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { violates: false };
|
|
69
|
+
}
|
package/dist/state-contract.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RevisionRecoveryInput, RevisionRecoveryResult } from './revision-recovery';
|
|
1
2
|
/** Transport types for the Rust-owned FeltDB state contract. */
|
|
2
3
|
export type PrimitiveType = 'string' | 'integer' | 'number' | 'boolean' | 'timestamp' | 'date' | 'time' | 'json' | 'uuid' | 'decimal' | 'money' | 'bigint' | 'email' | 'url' | 'phone' | 'binary' | 'file' | 'geo_point' | 'object';
|
|
3
4
|
export type FieldType = {
|
|
@@ -174,6 +175,7 @@ export declare class StateContractClient {
|
|
|
174
175
|
transactionId?: string;
|
|
175
176
|
causalParent?: number;
|
|
176
177
|
}): Promise<TransactionResult>;
|
|
178
|
+
recoverApplicationRevision(input: RevisionRecoveryInput): Promise<RevisionRecoveryResult>;
|
|
177
179
|
}
|
|
178
180
|
export {};
|
|
179
181
|
//# sourceMappingURL=state-contract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-contract.d.ts","sourceRoot":"","sources":["../src/state-contract.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"state-contract.d.ts","sourceRoot":"","sources":["../src/state-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAGpF,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAC,QAAQ,GAAC,SAAS,GAAC,QAAQ,GAAC,SAAS,GAAC,WAAW,GAAC,MAAM,GAAC,MAAM,GAAC,MAAM,GAAC,MAAM,GAAC,SAAS,GAAC,OAAO,GAAC,QAAQ,GAAC,OAAO,GAAC,KAAK,GAAC,OAAO,GAAC,QAAQ,GAAC,MAAM,GAAC,WAAW,GAAC,QAAQ,CAAC;AAC9L,MAAM,MAAM,SAAS,GAAC;IAAC,IAAI,EAAC,WAAW,CAAC;IAAA,SAAS,EAAC,aAAa,CAAA;CAAC,GAAC;IAAC,IAAI,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,MAAM,EAAE,CAAA;CAAC,GAAC;IAAC,IAAI,EAAC,WAAW,CAAC;IAAA,UAAU,EAAC,MAAM,CAAA;CAAC,GAAC;IAAC,IAAI,EAAC,OAAO,CAAC;IAAA,KAAK,EAAC,SAAS,CAAA;CAAC,GAAC;IAAC,IAAI,EAAC,KAAK,CAAC;IAAA,MAAM,EAAC,SAAS,CAAA;CAAC,GAAC;IAAC,IAAI,EAAC,QAAQ,CAAC;IAAA,UAAU,CAAC,EAAC,MAAM,CAAA;CAAC,CAAC;AACpO,MAAM,WAAW,UAAU;IAAC,IAAI,EAAC,MAAM,CAAC;IAAA,UAAU,EAAC,SAAS,CAAC;IAAA,QAAQ,CAAC,EAAC,OAAO,CAAC;IAAA,QAAQ,CAAC,EAAC,OAAO,CAAC;IAAA,OAAO,CAAC,EAAC,OAAO,CAAC;IAAA,WAAW,CAAC,EAAC;QAAC,OAAO,CAAC,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC;QAAA,UAAU,CAAC,EAAC,MAAM,CAAC;QAAA,UAAU,CAAC,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAA;KAAC,CAAC;IAAA,QAAQ,CAAC,EAAC,MAAM,CAAA;CAAC;AACxO,MAAM,WAAW,WAAW;IAAC,gBAAgB,EAAC,MAAM,CAAC;IAAA,cAAc,EAAC,MAAM,CAAC;IAAA,cAAc,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAA,OAAO,EAAC,MAAM,CAAC;QAAA,MAAM,EAAC,UAAU,EAAE,CAAC;QAAA,OAAO,EAAC;YAAC,IAAI,EAAC,MAAM,CAAC;YAAA,MAAM,EAAC,MAAM,EAAE,CAAC;YAAA,MAAM,CAAC,EAAC,OAAO,CAAC;YAAA,MAAM,CAAC,EAAC,OAAO,CAAC;YAAA,OAAO,EAAC,MAAM,CAAA;SAAC,EAAE,CAAA;KAAC,EAAE,CAAA;CAAC;AAC1Q,MAAM,MAAM,WAAW,GAAC;IAAC,QAAQ,EAAC,IAAI,GAAC,KAAK,GAAC,IAAI,GAAC,KAAK,GAAC,IAAI,GAAC,KAAK,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,KAAK,EAAC,OAAO,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,IAAI,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,OAAO,EAAE,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,UAAU,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,KAAK,EAAC,OAAO,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,YAAY,GAAC,UAAU,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,KAAK,EAAC,MAAM,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,QAAQ,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,OAAO,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,KAAK,GAAC,IAAI,CAAC;IAAA,OAAO,EAAC,WAAW,EAAE,CAAA;CAAC,GAAC;IAAC,QAAQ,EAAC,KAAK,CAAC;IAAA,MAAM,EAAC,WAAW,CAAA;CAAC,CAAC;AAC3X,MAAM,WAAW,cAAc;IAAC,UAAU,EAAC,MAAM,CAAC;IAAA,MAAM,CAAC,EAAC,WAAW,CAAC;IAAA,QAAQ,CAAC,EAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,KAAK,GAAC,MAAM,CAAA;KAAC,EAAE,CAAC;IAAA,KAAK,CAAC,EAAC,MAAM,CAAC;IAAA,MAAM,CAAC,EAAC,MAAM,CAAC;IAAA,MAAM,CAAC,EAAC,MAAM,CAAC;IAAA,UAAU,CAAC,EAAC,MAAM,EAAE,CAAC;IAAA,QAAQ,CAAC,EAAC,MAAM,EAAE,CAAC;IAAA,UAAU,CAAC,EAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAA,QAAQ,EAAC,OAAO,GAAC,KAAK,GAAC,KAAK,GAAC,KAAK,GAAC,KAAK,CAAC;QAAA,KAAK,CAAC,EAAC,MAAM,CAAA;KAAC,EAAE,CAAC;IAAA,UAAU,CAAC,EAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAA,UAAU,EAAC,MAAM,CAAC;QAAA,UAAU,CAAC,EAAC,MAAM,EAAE,CAAC;QAAA,OAAO,EAAC,MAAM,CAAA;KAAC,EAAE,CAAA;CAAC;AAClX,MAAM,WAAW,WAAW,CAAC,CAAC,GAAC,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC;IAAE,QAAQ,EAAC,MAAM,CAAC;IAAA,UAAU,EAAC,MAAM,CAAC;IAAA,oBAAoB,EAAC,MAAM,CAAC;IAAA,cAAc,EAAC,MAAM,CAAC;IAAA,aAAa,EAAC,MAAM,CAAC;IAAA,aAAa,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC;IAAA,OAAO,EAAC,CAAC,EAAE,CAAC;IAAA,UAAU,EAAC,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC,EAAE,CAAC;IAAA,WAAW,CAAC,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC;QAAC,cAAc,EAAC,MAAM,CAAC;QAAA,UAAU,EAAC,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,MAAM,CAAC;QAAA,aAAa,EAAC,OAAO,CAAA;KAAC,CAAA;CAAC;AAC3V,MAAM,WAAW,oBAAoB;IAAC,IAAI,EAAC,QAAQ,GAAC,QAAQ,GAAC,QAAQ,CAAC;IAAA,UAAU,EAAC,MAAM,CAAC;IAAA,EAAE,EAAC,MAAM,CAAC;IAAA,KAAK,CAAC,EAAC,OAAO,CAAC;IAAA,UAAU,CAAC,EAAC,MAAM,CAAA;CAAC;AACpI,MAAM,WAAW,iBAAiB;IAAC,cAAc,EAAC,MAAM,CAAC;IAAA,YAAY,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC,MAAM,CAAC;IAAA,aAAa,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC;IAAA,SAAS,EAAC,OAAO,CAAC;IAAA,KAAK,EAAC,OAAO,CAAA;CAAC;AACpK,MAAM,WAAW,YAAY;IAAC,IAAI,EAAC,mBAAmB,GAAC,qBAAqB,GAAC,sBAAsB,GAAC,iBAAiB,GAAC,UAAU,GAAC,iBAAiB,GAAC,eAAe,GAAC,eAAe,GAAC,oBAAoB,GAAC,yBAAyB,GAAC,gBAAgB,GAAC,mBAAmB,CAAC;IAAA,OAAO,EAAC,MAAM,CAAC;IAAA,QAAQ,CAAC,EAAC,OAAO,CAAC;IAAA,MAAM,CAAC,EAAC,OAAO,CAAC;IAAA,QAAQ,CAAC,EAAC,MAAM,CAAC;IAAA,WAAW,CAAC,EAAC,MAAM,CAAC;IAAA,eAAe,CAAC,EAAC,MAAM,CAAA;CAAC;AAErX,cAAM,kBAAkB;IACtB,QAAQ,CAAC,UAAU,EAAC,oBAAoB,EAAE,CAAI;IAC9C,UAAU,CAAC,IAAI,EAAC,MAAM;qBAAoB,MAAM,SAAO,OAAO;qBAA0F,MAAM,SAAO,OAAO,YAAU;YAAC,SAAS,CAAC,EAAC,MAAM,CAAA;SAAC;qBAA8G,MAAM,YAAU;YAAC,SAAS,CAAC,EAAC,MAAM,CAAA;SAAC;;CAC3V;AACD,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAA8D,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAA5F,MAAM,EAAC;QAAC,aAAa,EAAC,MAAM,CAAC;QAAA,UAAU,EAAC,MAAM,CAAC;QAAA,WAAW,CAAC,EAAC,MAAM,CAAA;KAAC,EAAkB,OAAO,SAAG;YAC9G,OAAO;IAmBrB,MAAM;gBAA4L,WAAW;;IAC7M,YAAY;IACZ,KAAK,CAAC,CAAC,GAAC,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC,EAAE,KAAK,EAAC,cAAc;IAC9C,WAAW,CAAC,IAAI,EAAC,CAAC,EAAE,EAAC,kBAAkB,KAAG,IAAI,GAAC,OAAO,CAAC,IAAI,CAAC,EAAC,OAAO,CAAC,EAAC;QAAC,aAAa,CAAC,EAAC,MAAM,CAAC;QAAA,YAAY,CAAC,EAAC,MAAM,CAAA;KAAC;IACxH,0BAA0B,CAAC,KAAK,EAAC,qBAAqB;CACvD"}
|
package/dist/state-contract.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FeltDBErrorCode } from './error-codes';
|
|
1
2
|
class TransactionBuilder {
|
|
2
3
|
constructor() {
|
|
3
4
|
this.operations = [];
|
|
@@ -9,16 +10,25 @@ export class StateContractClient {
|
|
|
9
10
|
this.target = target;
|
|
10
11
|
this.baseUrl = baseUrl;
|
|
11
12
|
}
|
|
12
|
-
async request(path, options) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
async request(path, options) {
|
|
14
|
+
const response = await fetch(`${this.baseUrl}${path}`, { ...options, headers: { ...(options?.body ? { 'Content-Type': 'application/json' } : {}), ...options?.headers } });
|
|
15
|
+
const body = await response.json();
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
const error = {
|
|
18
|
+
code: body.code || FeltDBErrorCode.INTERNAL_ERROR,
|
|
19
|
+
message: body.message || 'FeltDB request failed',
|
|
20
|
+
request_id: body.request_id || 'unknown',
|
|
21
|
+
transaction_id: body.transaction_id,
|
|
22
|
+
http_status: response.status,
|
|
23
|
+
recovery_hint: body.recovery_hint,
|
|
24
|
+
};
|
|
25
|
+
throw Object.assign(new Error(error.message), { status: response.status, feltdb_error: error });
|
|
16
26
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} return body; }
|
|
27
|
+
return body;
|
|
28
|
+
}
|
|
20
29
|
schema() { const q = new URLSearchParams({ application_id: this.target.applicationId, revision_id: this.target.revisionId, environment: this.target.environment || 'production' }); return this.request(`/v1/schema?${q}`); }
|
|
21
30
|
stateVersion() { const q = new URLSearchParams({ application_id: this.target.applicationId, revision_id: this.target.revisionId, environment: this.target.environment || 'production' }); return this.request(`/v1/state/version?${q}`); }
|
|
22
31
|
query(query) { return this.request('/v1/query', { method: 'POST', body: JSON.stringify({ application_id: this.target.applicationId, revision_id: this.target.revisionId, environment: this.target.environment || 'production', query }) }); }
|
|
23
32
|
async transaction(work, options) { const tx = new TransactionBuilder(); await work(tx); return this.request('/v1/transactions', { method: 'POST', body: JSON.stringify({ application_id: this.target.applicationId, revision_id: this.target.revisionId, environment: this.target.environment || 'production', transaction: { transaction_id: options?.transactionId, tenant_id: 'transport', application_id: this.target.applicationId, revision_id: this.target.revisionId, schema_version: 0, causal_parent: options?.causalParent, authorization: { subject: 'transport', tenant_id: 'transport', application_id: this.target.applicationId, revision_id: this.target.revisionId, capabilities: [] }, operations: tx.operations } }) }); }
|
|
33
|
+
recoverApplicationRevision(input) { return this.request('/v1/revision/recover', { method: 'POST', body: JSON.stringify({ ...input, environment: input.environment || this.target.environment || 'production' }) }); }
|
|
24
34
|
}
|