@company-semantics/contracts 0.82.0 → 0.83.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/package.json +1 -1
- package/src/execution/audit-export.ts +67 -0
- package/src/execution/event-metadata.ts +103 -0
- package/src/execution/events.ts +37 -0
- package/src/execution/hash-chain.ts +40 -0
- package/src/execution/index.ts +53 -0
- package/src/index.ts +4 -0
- package/src/message-parts/confirmation.ts +11 -0
- package/src/message-parts/index.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ExecutionEventType } from './events';
|
|
2
|
+
import type { ExecutionIntent } from './types';
|
|
3
|
+
import type { HashChainVerificationResult } from './hash-chain';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Immutable governance snapshot captured at execution creation time.
|
|
7
|
+
* Stored in execution_audit.frozen_intent JSONB column.
|
|
8
|
+
*
|
|
9
|
+
* Semantically distinct from ExecutionIntent: this represents what was true
|
|
10
|
+
* at creation time, not what the registry currently says.
|
|
11
|
+
* frozenIntentHash enables tamper detection if JSONB is modified by privileged DBA.
|
|
12
|
+
*/
|
|
13
|
+
export type FrozenExecutionIntent = Readonly<ExecutionIntent> & {
|
|
14
|
+
/** ISO 8601 timestamp of when this snapshot was captured */
|
|
15
|
+
frozenAt: string;
|
|
16
|
+
/** SHA-256 of canonicalized frozen intent — for tamper detection */
|
|
17
|
+
frozenIntentHash: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Per-event shape within an audit export bundle.
|
|
22
|
+
* Events MUST be ordered by eventSequence ascending.
|
|
23
|
+
*/
|
|
24
|
+
export interface AuditExportEvent {
|
|
25
|
+
eventSequence: number;
|
|
26
|
+
eventType: ExecutionEventType;
|
|
27
|
+
stateAfter: string;
|
|
28
|
+
actorId: string;
|
|
29
|
+
actorType: string;
|
|
30
|
+
metadata: Record<string, unknown>;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
eventHash: string;
|
|
33
|
+
previousHash: string | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Top-level audit export bundle for a single execution.
|
|
38
|
+
*
|
|
39
|
+
* Threat model:
|
|
40
|
+
* - hashChainValid: Detects internal DB tampering (single-row mutation)
|
|
41
|
+
* - frozenIntentHashValid: Detects frozen intent JSONB mutation
|
|
42
|
+
* - exportSignature (HMAC-SHA256): Proves this export was generated by this server.
|
|
43
|
+
* Does NOT prove DB was not tampered prior to export.
|
|
44
|
+
* Hash chaining + frozen intent hashing detect pre-export tampering.
|
|
45
|
+
*/
|
|
46
|
+
export interface AuditExportBundle {
|
|
47
|
+
/** Schema version for forward compatibility */
|
|
48
|
+
version: '1.0';
|
|
49
|
+
/** ISO 8601 timestamp of export generation */
|
|
50
|
+
exportedAt: string;
|
|
51
|
+
/** Execution ID */
|
|
52
|
+
executionId: string;
|
|
53
|
+
/** Organization ID */
|
|
54
|
+
orgId: string;
|
|
55
|
+
/** Frozen governance snapshot from execution_audit */
|
|
56
|
+
frozenIntent: FrozenExecutionIntent;
|
|
57
|
+
/** Whether frozen_intent_hash matches recomputed SHA-256(canonicalize(frozen_intent)) */
|
|
58
|
+
frozenIntentHashValid: boolean;
|
|
59
|
+
/** Event chain ordered by eventSequence ascending, with hash fields */
|
|
60
|
+
events: AuditExportEvent[];
|
|
61
|
+
/** Whether all event hashes recompute correctly */
|
|
62
|
+
hashChainValid: boolean;
|
|
63
|
+
/** Detailed chain verification result */
|
|
64
|
+
hashChainVerification: HashChainVerificationResult;
|
|
65
|
+
/** HMAC-SHA256 of bundle content. Present only if AUDIT_EXPORT_SIGNING_KEY is configured. */
|
|
66
|
+
exportSignature?: string;
|
|
67
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ExecutionEventType } from './events';
|
|
2
|
+
import type { ExecutionIntent } from './types';
|
|
3
|
+
|
|
4
|
+
/** Metadata for execution_created event. Frozen governance snapshot. */
|
|
5
|
+
export interface ExecutionCreatedMetadata {
|
|
6
|
+
/** Full ExecutionIntent frozen at creation time — authoritative governance snapshot (INV-18) */
|
|
7
|
+
executionIntent: ExecutionIntent;
|
|
8
|
+
/** Number of artifacts in the execution */
|
|
9
|
+
artifactCount: number;
|
|
10
|
+
/** ISO 8601 confirmation deadline. Present when requiresConfirmation=true. */
|
|
11
|
+
expiresAt?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Metadata for execution_started event. Intentionally empty. */
|
|
15
|
+
export type ExecutionStartedMetadata = Record<string, never>;
|
|
16
|
+
|
|
17
|
+
/** Metadata for confirmation_approved event. */
|
|
18
|
+
export interface ConfirmationApprovedMetadata {
|
|
19
|
+
/** userId of the user who confirmed */
|
|
20
|
+
confirmedBy: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Metadata for confirmation_rejected event. */
|
|
24
|
+
export interface ConfirmationRejectedMetadata {
|
|
25
|
+
/** userId of the user who rejected */
|
|
26
|
+
rejectedBy: string;
|
|
27
|
+
/** Optional reason for rejection */
|
|
28
|
+
reason?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Metadata for confirmation_expired event. */
|
|
32
|
+
export interface ConfirmationExpiredMetadata {
|
|
33
|
+
/** What triggered the expiration */
|
|
34
|
+
trigger: 'job' | 'confirm_attempt';
|
|
35
|
+
/** ISO 8601 timestamp when expiration was recorded */
|
|
36
|
+
expiredAt: string;
|
|
37
|
+
/** ISO 8601 original confirmation deadline */
|
|
38
|
+
originalExpiresAt: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Metadata for approval_requested event. Governance-metadata event. */
|
|
42
|
+
export interface ApprovalRequestedMetadata {
|
|
43
|
+
/** Reason approval is required */
|
|
44
|
+
reason: string;
|
|
45
|
+
/** userId who triggered the approval request */
|
|
46
|
+
requestedBy: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Metadata for execution_completed event. Forward-compatible. */
|
|
50
|
+
export interface ExecutionCompletedMetadata {
|
|
51
|
+
/** Human-readable result summary */
|
|
52
|
+
resultSummary?: string;
|
|
53
|
+
/** Number of artifacts executed */
|
|
54
|
+
artifactCount?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Metadata for execution_failed event. Forward-compatible. */
|
|
58
|
+
export interface ExecutionFailedMetadata {
|
|
59
|
+
/** Machine-readable error code */
|
|
60
|
+
errorCode?: string;
|
|
61
|
+
/** Error classification for retry decisions */
|
|
62
|
+
errorClass?: 'retryable' | 'terminal';
|
|
63
|
+
/** Human-readable error message */
|
|
64
|
+
message?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Metadata for undo_completed event. Forward-compatible. */
|
|
68
|
+
export interface UndoCompletedMetadata {
|
|
69
|
+
/** userId who initiated the undo */
|
|
70
|
+
undoneBy: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Metadata for cancelled event. Forward-compatible. */
|
|
74
|
+
export interface CancelledMetadata {
|
|
75
|
+
/** userId who cancelled */
|
|
76
|
+
cancelledBy: string;
|
|
77
|
+
/** Optional cancellation reason */
|
|
78
|
+
reason?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Exhaustive mapping from ExecutionEventType to its metadata interface.
|
|
83
|
+
* TypeScript enforces completeness — adding a new event type without
|
|
84
|
+
* a metadata definition here is a compile error.
|
|
85
|
+
*/
|
|
86
|
+
export interface ExecutionEventMetadataMap {
|
|
87
|
+
execution_created: ExecutionCreatedMetadata;
|
|
88
|
+
execution_started: ExecutionStartedMetadata;
|
|
89
|
+
confirmation_approved: ConfirmationApprovedMetadata;
|
|
90
|
+
confirmation_rejected: ConfirmationRejectedMetadata;
|
|
91
|
+
confirmation_expired: ConfirmationExpiredMetadata;
|
|
92
|
+
approval_requested: ApprovalRequestedMetadata;
|
|
93
|
+
execution_completed: ExecutionCompletedMetadata;
|
|
94
|
+
execution_failed: ExecutionFailedMetadata;
|
|
95
|
+
undo_completed: UndoCompletedMetadata;
|
|
96
|
+
cancelled: CancelledMetadata;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Compile-time exhaustiveness check: this line errors if
|
|
100
|
+
// ExecutionEventMetadataMap keys don't match ExecutionEventType
|
|
101
|
+
type _ExhaustivenessCheck = {
|
|
102
|
+
[K in ExecutionEventType]: ExecutionEventMetadataMap[K];
|
|
103
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumerates all valid event_type values for the execution_events table.
|
|
3
|
+
*
|
|
4
|
+
* Currently emitted: execution_created, execution_started, confirmation_approved,
|
|
5
|
+
* confirmation_rejected, confirmation_expired, approval_requested.
|
|
6
|
+
*
|
|
7
|
+
* Forward-compatible: execution_completed, execution_failed, undo_completed, cancelled.
|
|
8
|
+
* These are defined here for type exhaustiveness but not yet emitted by backend.
|
|
9
|
+
*/
|
|
10
|
+
export type ExecutionEventType =
|
|
11
|
+
| 'execution_created'
|
|
12
|
+
| 'execution_started'
|
|
13
|
+
| 'confirmation_approved'
|
|
14
|
+
| 'confirmation_rejected'
|
|
15
|
+
| 'confirmation_expired'
|
|
16
|
+
| 'approval_requested'
|
|
17
|
+
| 'execution_completed'
|
|
18
|
+
| 'execution_failed'
|
|
19
|
+
| 'undo_completed'
|
|
20
|
+
| 'cancelled';
|
|
21
|
+
|
|
22
|
+
export const EXECUTION_EVENT_TYPES: readonly ExecutionEventType[] = [
|
|
23
|
+
'execution_created',
|
|
24
|
+
'execution_started',
|
|
25
|
+
'confirmation_approved',
|
|
26
|
+
'confirmation_rejected',
|
|
27
|
+
'confirmation_expired',
|
|
28
|
+
'approval_requested',
|
|
29
|
+
'execution_completed',
|
|
30
|
+
'execution_failed',
|
|
31
|
+
'undo_completed',
|
|
32
|
+
'cancelled',
|
|
33
|
+
] as const;
|
|
34
|
+
|
|
35
|
+
export function isExecutionEventType(value: string): value is ExecutionEventType {
|
|
36
|
+
return (EXECUTION_EVENT_TYPES as readonly string[]).includes(value);
|
|
37
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash chain fields for tamper-evident execution events.
|
|
3
|
+
*
|
|
4
|
+
* Algorithm: SHA-256 over RFC 8785 JCS (JSON Canonicalization Scheme) input.
|
|
5
|
+
* Input: executionId + eventSequence + eventType + stateAfter + actorId + canonicalize(metadata) + (previousHash ?? 'NULL')
|
|
6
|
+
* created_at intentionally excluded — clock drift across replicas could break verification.
|
|
7
|
+
*
|
|
8
|
+
* Threat model: Detects single-row mutation where attacker does not recompute downstream hashes.
|
|
9
|
+
* Does NOT defend against fully malicious DBA who recomputes entire chain.
|
|
10
|
+
* External anchoring (periodic anchor hash stored outside DB) is a future enhancement.
|
|
11
|
+
*/
|
|
12
|
+
export interface EventHashFields {
|
|
13
|
+
/** SHA-256 hex digest (64 characters) of this event's canonicalized content */
|
|
14
|
+
eventHash: string;
|
|
15
|
+
/** SHA-256 hex digest of the previous event in this execution's chain, or null for the first event */
|
|
16
|
+
previousHash: string | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Result of verifying a hash chain for a single execution.
|
|
21
|
+
* If valid=false, brokenAtSequence indicates where the chain first breaks.
|
|
22
|
+
*/
|
|
23
|
+
export interface HashChainVerificationResult {
|
|
24
|
+
/** True if all event hashes recompute correctly and chain links are valid */
|
|
25
|
+
valid: boolean;
|
|
26
|
+
/** Event sequence number where chain integrity first fails (present only if valid=false) */
|
|
27
|
+
brokenAtSequence?: number;
|
|
28
|
+
/** What the recomputed hash should be (present only if valid=false) */
|
|
29
|
+
expectedHash?: string;
|
|
30
|
+
/** What was stored in the database (present only if valid=false) */
|
|
31
|
+
actualHash?: string;
|
|
32
|
+
/** True if frozen_intent_hash verification failed (present only if checked) */
|
|
33
|
+
frozenIntentMismatch?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Hash algorithm used for event chain integrity */
|
|
37
|
+
export const HASH_ALGORITHM = 'sha256' as const;
|
|
38
|
+
|
|
39
|
+
/** Encoding for hash output */
|
|
40
|
+
export const HASH_ENCODING = 'hex' as const;
|
package/src/execution/index.ts
CHANGED
|
@@ -7,6 +7,59 @@
|
|
|
7
7
|
* @see ADR-CONT-029 for design rationale
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Event Types
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
export type { ExecutionEventType } from './events'
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
EXECUTION_EVENT_TYPES,
|
|
18
|
+
isExecutionEventType,
|
|
19
|
+
} from './events'
|
|
20
|
+
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Event Metadata Schemas
|
|
23
|
+
// =============================================================================
|
|
24
|
+
|
|
25
|
+
export type {
|
|
26
|
+
ExecutionCreatedMetadata,
|
|
27
|
+
ExecutionStartedMetadata,
|
|
28
|
+
ConfirmationApprovedMetadata,
|
|
29
|
+
ConfirmationRejectedMetadata,
|
|
30
|
+
ConfirmationExpiredMetadata,
|
|
31
|
+
ApprovalRequestedMetadata,
|
|
32
|
+
ExecutionCompletedMetadata,
|
|
33
|
+
ExecutionFailedMetadata,
|
|
34
|
+
UndoCompletedMetadata,
|
|
35
|
+
CancelledMetadata,
|
|
36
|
+
ExecutionEventMetadataMap,
|
|
37
|
+
} from './event-metadata'
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Hash Chain Types
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export type {
|
|
44
|
+
EventHashFields,
|
|
45
|
+
HashChainVerificationResult,
|
|
46
|
+
} from './hash-chain'
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
HASH_ALGORITHM,
|
|
50
|
+
HASH_ENCODING,
|
|
51
|
+
} from './hash-chain'
|
|
52
|
+
|
|
53
|
+
// =============================================================================
|
|
54
|
+
// Audit Export Types
|
|
55
|
+
// =============================================================================
|
|
56
|
+
|
|
57
|
+
export type {
|
|
58
|
+
FrozenExecutionIntent,
|
|
59
|
+
AuditExportEvent,
|
|
60
|
+
AuditExportBundle,
|
|
61
|
+
} from './audit-export'
|
|
62
|
+
|
|
10
63
|
// =============================================================================
|
|
11
64
|
// Kind Types
|
|
12
65
|
// =============================================================================
|
package/src/index.ts
CHANGED
|
@@ -305,6 +305,7 @@ export type {
|
|
|
305
305
|
ConfirmationChoice,
|
|
306
306
|
ConfirmationRiskLevel,
|
|
307
307
|
ConfirmationData,
|
|
308
|
+
ConfirmationResponseData,
|
|
308
309
|
ConfirmationDataPart,
|
|
309
310
|
// Execution result types (Phase 5)
|
|
310
311
|
ExecutionArtifactStatus,
|
|
@@ -350,6 +351,7 @@ export {
|
|
|
350
351
|
export type {
|
|
351
352
|
ExecutionKind,
|
|
352
353
|
ExecutionState,
|
|
354
|
+
ExecutionEventType,
|
|
353
355
|
ISO8601Timestamp,
|
|
354
356
|
IconName,
|
|
355
357
|
ExecutionDomain,
|
|
@@ -368,6 +370,8 @@ export {
|
|
|
368
370
|
EXECUTION_KINDS,
|
|
369
371
|
getExecutionKindDefinition,
|
|
370
372
|
isValidExecutionKind,
|
|
373
|
+
EXECUTION_EVENT_TYPES,
|
|
374
|
+
isExecutionEventType,
|
|
371
375
|
} from './execution/index'
|
|
372
376
|
|
|
373
377
|
// Ralph autonomous coding loop types
|
|
@@ -69,6 +69,17 @@ export interface ConfirmationData {
|
|
|
69
69
|
/**
|
|
70
70
|
* Confirmation request message part (semantic type).
|
|
71
71
|
*/
|
|
72
|
+
/**
|
|
73
|
+
* Data sent by the client to confirm or cancel a proposed action.
|
|
74
|
+
* Structured response only — no natural language inference.
|
|
75
|
+
*/
|
|
76
|
+
export interface ConfirmationResponseData {
|
|
77
|
+
/** Must match the active preview's actionId */
|
|
78
|
+
actionId: string;
|
|
79
|
+
/** User's explicit decision */
|
|
80
|
+
choice: ConfirmationChoice;
|
|
81
|
+
}
|
|
82
|
+
|
|
72
83
|
export interface ConfirmationPart {
|
|
73
84
|
type: 'confirmation';
|
|
74
85
|
data: ConfirmationData;
|