@agirails/sdk 2.7.0 → 3.1.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 +1 -1
- package/bin/agirails +10 -0
- package/dist/ACTPClient.d.ts +15 -4
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +20 -8
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/ACTPKernel.json +87 -6
- package/dist/adapters/BaseAdapter.d.ts +3 -3
- package/dist/adapters/BaseAdapter.js +3 -3
- package/dist/adapters/BasicAdapter.d.ts +1 -1
- package/dist/adapters/BasicAdapter.js +2 -2
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/StandardAdapter.d.ts +30 -8
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +34 -9
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/api/agirailsApp.d.ts +197 -0
- package/dist/api/agirailsApp.d.ts.map +1 -0
- package/dist/api/agirailsApp.js +175 -0
- package/dist/api/agirailsApp.js.map +1 -0
- package/dist/cli/agirails.d.ts +10 -0
- package/dist/cli/agirails.d.ts.map +1 -0
- package/dist/cli/agirails.js +187 -0
- package/dist/cli/agirails.js.map +1 -0
- package/dist/cli/commands/autopublish.d.ts +13 -0
- package/dist/cli/commands/autopublish.d.ts.map +1 -0
- package/dist/cli/commands/autopublish.js +156 -0
- package/dist/cli/commands/autopublish.js.map +1 -0
- package/dist/cli/commands/batch.js +1 -1
- package/dist/cli/commands/claim-code.d.ts +11 -0
- package/dist/cli/commands/claim-code.d.ts.map +1 -0
- package/dist/cli/commands/claim-code.js +160 -0
- package/dist/cli/commands/claim-code.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +17 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +104 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/config.js +1 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/find.d.ts +23 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +230 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/health.d.ts +16 -0
- package/dist/cli/commands/health.d.ts.map +1 -0
- package/dist/cli/commands/health.js +287 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +42 -13
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/negotiate.d.ts +11 -0
- package/dist/cli/commands/negotiate.d.ts.map +1 -0
- package/dist/cli/commands/negotiate.js +192 -0
- package/dist/cli/commands/negotiate.js.map +1 -0
- package/dist/cli/commands/publish.d.ts.map +1 -1
- package/dist/cli/commands/publish.js +313 -18
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/pull.d.ts +7 -3
- package/dist/cli/commands/pull.d.ts.map +1 -1
- package/dist/cli/commands/pull.js +105 -13
- package/dist/cli/commands/pull.js.map +1 -1
- package/dist/cli/commands/receipt.d.ts +31 -0
- package/dist/cli/commands/receipt.d.ts.map +1 -0
- package/dist/cli/commands/receipt.js +92 -0
- package/dist/cli/commands/receipt.js.map +1 -0
- package/dist/cli/commands/test.d.ts +15 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/test.js +176 -0
- package/dist/cli/commands/test.js.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/testjobs/index.d.ts +18 -0
- package/dist/cli/testjobs/index.d.ts.map +1 -0
- package/dist/cli/testjobs/index.js +45 -0
- package/dist/cli/testjobs/index.js.map +1 -0
- package/dist/cli/testjobs/templates/automation.d.ts +3 -0
- package/dist/cli/testjobs/templates/automation.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/automation.js +32 -0
- package/dist/cli/testjobs/templates/automation.js.map +1 -0
- package/dist/cli/testjobs/templates/code-review.d.ts +3 -0
- package/dist/cli/testjobs/templates/code-review.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/code-review.js +27 -0
- package/dist/cli/testjobs/templates/code-review.js.map +1 -0
- package/dist/cli/testjobs/templates/content-writing.d.ts +3 -0
- package/dist/cli/testjobs/templates/content-writing.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/content-writing.js +20 -0
- package/dist/cli/testjobs/templates/content-writing.js.map +1 -0
- package/dist/cli/testjobs/templates/data-analysis.d.ts +3 -0
- package/dist/cli/testjobs/templates/data-analysis.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/data-analysis.js +34 -0
- package/dist/cli/testjobs/templates/data-analysis.js.map +1 -0
- package/dist/cli/testjobs/templates/generic.d.ts +3 -0
- package/dist/cli/testjobs/templates/generic.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/generic.js +17 -0
- package/dist/cli/testjobs/templates/generic.js.map +1 -0
- package/dist/cli/testjobs/templates/security-audit.d.ts +3 -0
- package/dist/cli/testjobs/templates/security-audit.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/security-audit.js +30 -0
- package/dist/cli/testjobs/templates/security-audit.js.map +1 -0
- package/dist/cli/testjobs/templates/testing.d.ts +3 -0
- package/dist/cli/testjobs/templates/testing.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/testing.js +29 -0
- package/dist/cli/testjobs/templates/testing.js.map +1 -0
- package/dist/cli/testjobs/templates/translation.d.ts +3 -0
- package/dist/cli/testjobs/templates/translation.d.ts.map +1 -0
- package/dist/cli/testjobs/templates/translation.js +16 -0
- package/dist/cli/testjobs/templates/translation.js.map +1 -0
- package/dist/cli/testjobs/types.d.ts +16 -0
- package/dist/cli/testjobs/types.d.ts.map +1 -0
- package/dist/cli/testjobs/types.js +8 -0
- package/dist/cli/testjobs/types.js.map +1 -0
- package/dist/cli/utils/client.js +1 -1
- package/dist/cli/utils/client.js.map +1 -1
- package/dist/cli/utils/config.d.ts +12 -0
- package/dist/cli/utils/config.d.ts.map +1 -1
- package/dist/cli/utils/config.js +29 -2
- package/dist/cli/utils/config.js.map +1 -1
- package/dist/config/agirailsmd.d.ts +1 -1
- package/dist/config/agirailsmd.d.ts.map +1 -1
- package/dist/config/agirailsmd.js +3 -0
- package/dist/config/agirailsmd.js.map +1 -1
- package/dist/config/agirailsmdV4.d.ts +82 -0
- package/dist/config/agirailsmdV4.d.ts.map +1 -0
- package/dist/config/agirailsmdV4.js +260 -0
- package/dist/config/agirailsmdV4.js.map +1 -0
- package/dist/config/defaults.d.ts +50 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +77 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/networks.d.ts +1 -0
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +16 -13
- package/dist/config/networks.js.map +1 -1
- package/dist/config/publishPipeline.d.ts.map +1 -1
- package/dist/config/publishPipeline.js +4 -0
- package/dist/config/publishPipeline.js.map +1 -1
- package/dist/config/slugUtils.d.ts +28 -0
- package/dist/config/slugUtils.d.ts.map +1 -0
- package/dist/config/slugUtils.js +51 -0
- package/dist/config/slugUtils.js.map +1 -0
- package/dist/level0/ServiceDirectory.d.ts +6 -6
- package/dist/level0/ServiceDirectory.js +11 -11
- package/dist/level0/ServiceDirectory.js.map +1 -1
- package/dist/level1/Agent.d.ts +10 -10
- package/dist/level1/Agent.d.ts.map +1 -1
- package/dist/level1/Agent.js +45 -29
- package/dist/level1/Agent.js.map +1 -1
- package/dist/level1/pricing/PriceCalculator.js +2 -2
- package/dist/level1/pricing/PriceCalculator.js.map +1 -1
- package/dist/negotiation/BuyerOrchestrator.d.ts +108 -0
- package/dist/negotiation/BuyerOrchestrator.d.ts.map +1 -0
- package/dist/negotiation/BuyerOrchestrator.js +377 -0
- package/dist/negotiation/BuyerOrchestrator.js.map +1 -0
- package/dist/negotiation/DecisionEngine.d.ts +44 -0
- package/dist/negotiation/DecisionEngine.d.ts.map +1 -0
- package/dist/negotiation/DecisionEngine.js +116 -0
- package/dist/negotiation/DecisionEngine.js.map +1 -0
- package/dist/negotiation/PolicyEngine.d.ts +126 -0
- package/dist/negotiation/PolicyEngine.d.ts.map +1 -0
- package/dist/negotiation/PolicyEngine.js +265 -0
- package/dist/negotiation/PolicyEngine.js.map +1 -0
- package/dist/negotiation/SessionStore.d.ts +57 -0
- package/dist/negotiation/SessionStore.d.ts.map +1 -0
- package/dist/negotiation/SessionStore.js +179 -0
- package/dist/negotiation/SessionStore.js.map +1 -0
- package/dist/negotiation/index.d.ts +9 -0
- package/dist/negotiation/index.d.ts.map +1 -0
- package/dist/negotiation/index.js +12 -0
- package/dist/negotiation/index.js.map +1 -0
- package/dist/protocol/ACTPKernel.d.ts +32 -4
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +70 -16
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/AgentRegistry.js +2 -2
- package/dist/protocol/AgentRegistry.js.map +1 -1
- package/dist/protocol/DIDResolver.js +2 -2
- package/dist/protocol/DIDResolver.js.map +1 -1
- package/dist/protocol/EASHelper.d.ts +2 -2
- package/dist/protocol/EASHelper.js +5 -5
- package/dist/protocol/EASHelper.js.map +1 -1
- package/dist/protocol/EscrowVault.d.ts +2 -2
- package/dist/protocol/EscrowVault.js +4 -4
- package/dist/protocol/EscrowVault.js.map +1 -1
- package/dist/protocol/EventMonitor.d.ts +4 -4
- package/dist/protocol/EventMonitor.js +5 -5
- package/dist/protocol/EventMonitor.js.map +1 -1
- package/dist/protocol/MessageSigner.d.ts +5 -5
- package/dist/protocol/MessageSigner.js +8 -8
- package/dist/protocol/MessageSigner.js.map +1 -1
- package/dist/protocol/ProofGenerator.d.ts +4 -4
- package/dist/protocol/ProofGenerator.js +6 -6
- package/dist/protocol/ProofGenerator.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts +36 -14
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +78 -45
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/runtime/IACTPRuntime.d.ts +12 -1
- package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.d.ts +29 -9
- package/dist/runtime/MockRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.js +88 -24
- package/dist/runtime/MockRuntime.js.map +1 -1
- package/dist/runtime/MockStateManager.js +2 -2
- package/dist/runtime/MockStateManager.js.map +1 -1
- package/dist/runtime/types/MockState.d.ts +1 -1
- package/dist/settle/SettleOnInteract.d.ts +32 -0
- package/dist/settle/SettleOnInteract.d.ts.map +1 -0
- package/dist/settle/SettleOnInteract.js +74 -0
- package/dist/settle/SettleOnInteract.js.map +1 -0
- package/dist/types/erc8004.d.ts +2 -2
- package/dist/types/erc8004.d.ts.map +1 -1
- package/dist/types/erc8004.js +4 -1
- package/dist/types/erc8004.js.map +1 -1
- package/dist/types/state.d.ts +1 -1
- package/dist/types/state.js +1 -1
- package/dist/types/transaction.d.ts +4 -0
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/utils/ErrorRecoveryGuide.d.ts +1 -1
- package/dist/utils/ErrorRecoveryGuide.js +1 -1
- package/dist/utils/Helpers.d.ts +6 -6
- package/dist/utils/Helpers.js +7 -7
- package/dist/utils/Helpers.js.map +1 -1
- package/dist/utils/IPFSClient.d.ts +7 -7
- package/dist/utils/IPFSClient.js +9 -9
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/Logger.d.ts +4 -4
- package/dist/utils/Logger.js +8 -8
- package/dist/utils/Logger.js.map +1 -1
- package/dist/utils/NonceManager.d.ts +9 -9
- package/dist/utils/NonceManager.js +19 -19
- package/dist/utils/NonceManager.js.map +1 -1
- package/dist/utils/RateLimiter.d.ts +10 -10
- package/dist/utils/RateLimiter.d.ts.map +1 -1
- package/dist/utils/RateLimiter.js +22 -22
- package/dist/utils/RateLimiter.js.map +1 -1
- package/dist/utils/ReceivedNonceTracker.d.ts +10 -10
- package/dist/utils/ReceivedNonceTracker.js +20 -20
- package/dist/utils/ReceivedNonceTracker.js.map +1 -1
- package/dist/utils/SDKLifecycle.d.ts +3 -3
- package/dist/utils/SDKLifecycle.js +7 -7
- package/dist/utils/SDKLifecycle.js.map +1 -1
- package/dist/utils/SecureNonce.d.ts +1 -1
- package/dist/utils/SecureNonce.js +1 -1
- package/dist/utils/Semaphore.d.ts +2 -2
- package/dist/utils/Semaphore.js +2 -2
- package/dist/utils/UsedAttestationTracker.d.ts +13 -13
- package/dist/utils/UsedAttestationTracker.js +20 -20
- package/dist/utils/UsedAttestationTracker.js.map +1 -1
- package/dist/utils/security.d.ts +3 -3
- package/dist/utils/security.js +4 -4
- package/dist/utils/security.js.map +1 -1
- package/dist/utils/validation.d.ts +4 -4
- package/dist/utils/validation.js +9 -9
- package/dist/utils/validation.js.map +1 -1
- package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
- package/dist/wallet/AutoWalletProvider.js +2 -1
- package/dist/wallet/AutoWalletProvider.js.map +1 -1
- package/dist/wallet/IWalletProvider.d.ts +2 -0
- package/dist/wallet/IWalletProvider.d.ts.map +1 -1
- package/dist/wallet/aa/TransactionBatcher.d.ts +22 -2
- package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -1
- package/dist/wallet/aa/TransactionBatcher.js +51 -9
- package/dist/wallet/aa/TransactionBatcher.js.map +1 -1
- package/package.json +6 -12
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PolicyEngine — Hard guardrails for autonomous negotiation.
|
|
3
|
+
*
|
|
4
|
+
* 5 non-negotiable checks before any escrow commitment:
|
|
5
|
+
* 1. unit_price <= max_unit_price
|
|
6
|
+
* 2. committed_today + projected_cost <= max_daily_spend
|
|
7
|
+
* 3. provider reputation >= min_reputation (if defined) — unknown = fail
|
|
8
|
+
* 4. quote not expired (within quote_ttl)
|
|
9
|
+
* 5. valid commerce_session_id
|
|
10
|
+
*
|
|
11
|
+
* Daily budget ledger persisted to `.actp/budget-ledger.json`
|
|
12
|
+
* using atomic write pattern (write-to-tmp + renameSync).
|
|
13
|
+
* Budget resets at UTC midnight.
|
|
14
|
+
*/
|
|
15
|
+
export interface BuyerPolicy {
|
|
16
|
+
task: string;
|
|
17
|
+
constraints: {
|
|
18
|
+
max_unit_price: {
|
|
19
|
+
amount: number;
|
|
20
|
+
currency: string;
|
|
21
|
+
unit: string;
|
|
22
|
+
};
|
|
23
|
+
max_daily_spend: {
|
|
24
|
+
amount: number;
|
|
25
|
+
currency: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
negotiation: {
|
|
29
|
+
rounds_max: number;
|
|
30
|
+
quote_ttl: string;
|
|
31
|
+
};
|
|
32
|
+
selection: {
|
|
33
|
+
min_reputation?: number;
|
|
34
|
+
prioritize: ('quality' | 'price' | 'speed' | 'reliability')[];
|
|
35
|
+
weights?: {
|
|
36
|
+
quality?: number;
|
|
37
|
+
price?: number;
|
|
38
|
+
speed?: number;
|
|
39
|
+
reliability?: number;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface QuoteOffer {
|
|
44
|
+
provider: string;
|
|
45
|
+
unit_price: number;
|
|
46
|
+
currency: string;
|
|
47
|
+
unit: string;
|
|
48
|
+
/** Total projected cost for this job (unit_price * quantity). Falls back to unit_price if omitted. */
|
|
49
|
+
total_price?: number;
|
|
50
|
+
expires_at?: number;
|
|
51
|
+
reputation_score?: number;
|
|
52
|
+
commerce_session_id?: string;
|
|
53
|
+
/** Signal that this is a final offer — no further negotiation expected */
|
|
54
|
+
final_offer?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export type PolicyViolation = {
|
|
57
|
+
rule: 'max_unit_price';
|
|
58
|
+
detail: string;
|
|
59
|
+
} | {
|
|
60
|
+
rule: 'max_daily_spend';
|
|
61
|
+
detail: string;
|
|
62
|
+
} | {
|
|
63
|
+
rule: 'min_reputation';
|
|
64
|
+
detail: string;
|
|
65
|
+
} | {
|
|
66
|
+
rule: 'quote_expired';
|
|
67
|
+
detail: string;
|
|
68
|
+
} | {
|
|
69
|
+
rule: 'missing_session_id';
|
|
70
|
+
detail: string;
|
|
71
|
+
};
|
|
72
|
+
export interface PolicyResult {
|
|
73
|
+
allowed: boolean;
|
|
74
|
+
violations: PolicyViolation[];
|
|
75
|
+
}
|
|
76
|
+
/** Single entry in the daily budget ledger */
|
|
77
|
+
export interface BudgetEntry {
|
|
78
|
+
commerce_session_id: string;
|
|
79
|
+
actp_tx_id?: string;
|
|
80
|
+
amount: number;
|
|
81
|
+
currency: string;
|
|
82
|
+
status: 'reserved' | 'committed' | 'released';
|
|
83
|
+
created_at: string;
|
|
84
|
+
}
|
|
85
|
+
export declare class PolicyEngine {
|
|
86
|
+
private policy;
|
|
87
|
+
private actpDir;
|
|
88
|
+
private ledger;
|
|
89
|
+
constructor(policy: BuyerPolicy, actpDir?: string);
|
|
90
|
+
/**
|
|
91
|
+
* Validate a quote offer against all 5 policy guardrails.
|
|
92
|
+
*/
|
|
93
|
+
validate(offer: QuoteOffer): PolicyResult;
|
|
94
|
+
/**
|
|
95
|
+
* Reserve budget for a pending commitment.
|
|
96
|
+
* Throws if the reservation would exceed max_daily_spend.
|
|
97
|
+
*/
|
|
98
|
+
reserve(sessionId: string, amount: number, currency: string): void;
|
|
99
|
+
/**
|
|
100
|
+
* Commit a reservation (after escrow linked).
|
|
101
|
+
*/
|
|
102
|
+
commit(sessionId: string, actpTxId: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* Release a reservation (after cancel/dispute).
|
|
105
|
+
*/
|
|
106
|
+
release(sessionId: string): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get total committed + reserved exposure for today.
|
|
109
|
+
*/
|
|
110
|
+
getCommittedToday(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Parse a TTL string like "15m" or "2h" into seconds.
|
|
113
|
+
*/
|
|
114
|
+
static parseTtl(ttl: string): number;
|
|
115
|
+
/**
|
|
116
|
+
* Get the quote TTL deadline (unix timestamp).
|
|
117
|
+
*/
|
|
118
|
+
getQuoteDeadline(): number;
|
|
119
|
+
private getLedgerPath;
|
|
120
|
+
private todayString;
|
|
121
|
+
private ensureLedgerCurrent;
|
|
122
|
+
private loadLedger;
|
|
123
|
+
private ensureDir;
|
|
124
|
+
private saveLedger;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=PolicyEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PolicyEngine.d.ts","sourceRoot":"","sources":["../../src/negotiation/PolicyEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PolicyEngine — Hard guardrails for autonomous negotiation.
|
|
4
|
+
*
|
|
5
|
+
* 5 non-negotiable checks before any escrow commitment:
|
|
6
|
+
* 1. unit_price <= max_unit_price
|
|
7
|
+
* 2. committed_today + projected_cost <= max_daily_spend
|
|
8
|
+
* 3. provider reputation >= min_reputation (if defined) — unknown = fail
|
|
9
|
+
* 4. quote not expired (within quote_ttl)
|
|
10
|
+
* 5. valid commerce_session_id
|
|
11
|
+
*
|
|
12
|
+
* Daily budget ledger persisted to `.actp/budget-ledger.json`
|
|
13
|
+
* using atomic write pattern (write-to-tmp + renameSync).
|
|
14
|
+
* Budget resets at UTC midnight.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PolicyEngine = void 0;
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// PolicyEngine
|
|
22
|
+
// ============================================================================
|
|
23
|
+
class PolicyEngine {
|
|
24
|
+
constructor(policy, actpDir) {
|
|
25
|
+
this.policy = policy;
|
|
26
|
+
this.actpDir = actpDir ?? (process.env.ACTP_DIR || (0, path_1.join)(process.cwd(), '.actp'));
|
|
27
|
+
this.ledger = this.loadLedger();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate a quote offer against all 5 policy guardrails.
|
|
31
|
+
*/
|
|
32
|
+
validate(offer) {
|
|
33
|
+
const violations = [];
|
|
34
|
+
// 0. Sanity check — reject NaN, negative, non-finite prices
|
|
35
|
+
if (!Number.isFinite(offer.unit_price) || offer.unit_price < 0) {
|
|
36
|
+
return {
|
|
37
|
+
allowed: false,
|
|
38
|
+
violations: [{ rule: 'max_unit_price', detail: `Invalid unit_price: ${offer.unit_price} (must be finite and >= 0)` }],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (offer.total_price != null && (!Number.isFinite(offer.total_price) || offer.total_price < 0)) {
|
|
42
|
+
return {
|
|
43
|
+
allowed: false,
|
|
44
|
+
violations: [{ rule: 'max_daily_spend', detail: `Invalid total_price: ${offer.total_price} (must be finite and >= 0)` }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// 1. Unit price check (with currency/unit consistency enforcement)
|
|
48
|
+
if (offer.currency.toUpperCase() !== this.policy.constraints.max_unit_price.currency.toUpperCase()) {
|
|
49
|
+
violations.push({
|
|
50
|
+
rule: 'max_unit_price',
|
|
51
|
+
detail: `Currency mismatch: offer is ${offer.currency}, policy requires ${this.policy.constraints.max_unit_price.currency}`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else if (offer.unit !== this.policy.constraints.max_unit_price.unit) {
|
|
55
|
+
violations.push({
|
|
56
|
+
rule: 'max_unit_price',
|
|
57
|
+
detail: `Unit mismatch: offer is per-${offer.unit}, policy requires per-${this.policy.constraints.max_unit_price.unit}`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else if (offer.unit_price > this.policy.constraints.max_unit_price.amount) {
|
|
61
|
+
violations.push({
|
|
62
|
+
rule: 'max_unit_price',
|
|
63
|
+
detail: `${offer.unit_price} ${offer.currency}/${offer.unit} exceeds max ${this.policy.constraints.max_unit_price.amount} ${this.policy.constraints.max_unit_price.currency}/${this.policy.constraints.max_unit_price.unit}`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// 2. Daily spend check (with currency consistency)
|
|
67
|
+
const projectedCost = offer.total_price ?? offer.unit_price;
|
|
68
|
+
if (offer.currency.toUpperCase() !== this.policy.constraints.max_daily_spend.currency.toUpperCase()) {
|
|
69
|
+
violations.push({
|
|
70
|
+
rule: 'max_daily_spend',
|
|
71
|
+
detail: `Currency mismatch: offer is ${offer.currency}, daily spend limit is ${this.policy.constraints.max_daily_spend.currency}`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const committedToday = this.getCommittedToday();
|
|
76
|
+
const projectedTotal = committedToday + projectedCost;
|
|
77
|
+
if (projectedTotal > this.policy.constraints.max_daily_spend.amount) {
|
|
78
|
+
violations.push({
|
|
79
|
+
rule: 'max_daily_spend',
|
|
80
|
+
detail: `Committed today: ${committedToday}, projected: ${projectedTotal}, max: ${this.policy.constraints.max_daily_spend.amount} ${this.policy.constraints.max_daily_spend.currency}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 3. Reputation check — unknown (missing score) = fail when min_reputation is set
|
|
85
|
+
if (this.policy.selection.min_reputation != null) {
|
|
86
|
+
if (offer.reputation_score == null ||
|
|
87
|
+
offer.reputation_score < this.policy.selection.min_reputation) {
|
|
88
|
+
violations.push({
|
|
89
|
+
rule: 'min_reputation',
|
|
90
|
+
detail: offer.reputation_score == null
|
|
91
|
+
? `Provider reputation unknown — min ${this.policy.selection.min_reputation} required`
|
|
92
|
+
: `Provider reputation ${offer.reputation_score} below minimum ${this.policy.selection.min_reputation}`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 4. Quote expiry check
|
|
97
|
+
if (offer.expires_at != null && offer.expires_at <= Math.floor(Date.now() / 1000)) {
|
|
98
|
+
violations.push({
|
|
99
|
+
rule: 'quote_expired',
|
|
100
|
+
detail: `Quote expired at ${new Date(offer.expires_at * 1000).toISOString()}`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// 5. Session ID check
|
|
104
|
+
if (!offer.commerce_session_id) {
|
|
105
|
+
violations.push({
|
|
106
|
+
rule: 'missing_session_id',
|
|
107
|
+
detail: 'No commerce_session_id provided',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
allowed: violations.length === 0,
|
|
112
|
+
violations,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Reserve budget for a pending commitment.
|
|
117
|
+
* Throws if the reservation would exceed max_daily_spend.
|
|
118
|
+
*/
|
|
119
|
+
reserve(sessionId, amount, currency) {
|
|
120
|
+
if (!Number.isFinite(amount) || amount < 0) {
|
|
121
|
+
throw new Error(`Invalid reserve amount: ${amount} (must be finite and >= 0)`);
|
|
122
|
+
}
|
|
123
|
+
const policyCurrency = this.policy.constraints.max_daily_spend.currency;
|
|
124
|
+
if (currency.toUpperCase() !== policyCurrency.toUpperCase()) {
|
|
125
|
+
throw new Error(`Currency mismatch in reserve: ${currency} does not match policy currency ${policyCurrency}`);
|
|
126
|
+
}
|
|
127
|
+
this.ensureLedgerCurrent();
|
|
128
|
+
// Enforce budget at reservation time (defense in depth — not just in validate())
|
|
129
|
+
const committedToday = this.getCommittedToday();
|
|
130
|
+
if (committedToday + amount > this.policy.constraints.max_daily_spend.amount) {
|
|
131
|
+
throw new Error(`Budget exceeded: reserving ${amount} ${currency} would exceed daily limit ` +
|
|
132
|
+
`${this.policy.constraints.max_daily_spend.amount} ${this.policy.constraints.max_daily_spend.currency} ` +
|
|
133
|
+
`(already committed: ${committedToday})`);
|
|
134
|
+
}
|
|
135
|
+
this.ledger.entries.push({
|
|
136
|
+
commerce_session_id: sessionId,
|
|
137
|
+
amount,
|
|
138
|
+
currency,
|
|
139
|
+
status: 'reserved',
|
|
140
|
+
created_at: new Date().toISOString(),
|
|
141
|
+
});
|
|
142
|
+
this.saveLedger();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Commit a reservation (after escrow linked).
|
|
146
|
+
*/
|
|
147
|
+
commit(sessionId, actpTxId) {
|
|
148
|
+
const entry = this.ledger.entries.find((e) => e.commerce_session_id === sessionId && e.status === 'reserved');
|
|
149
|
+
if (entry) {
|
|
150
|
+
entry.status = 'committed';
|
|
151
|
+
entry.actp_tx_id = actpTxId;
|
|
152
|
+
this.saveLedger();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Release a reservation (after cancel/dispute).
|
|
157
|
+
*/
|
|
158
|
+
release(sessionId) {
|
|
159
|
+
const entry = this.ledger.entries.find((e) => e.commerce_session_id === sessionId && (e.status === 'reserved' || e.status === 'committed'));
|
|
160
|
+
if (entry) {
|
|
161
|
+
entry.status = 'released';
|
|
162
|
+
this.saveLedger();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get total committed + reserved exposure for today.
|
|
167
|
+
*/
|
|
168
|
+
getCommittedToday() {
|
|
169
|
+
this.ensureLedgerCurrent();
|
|
170
|
+
return this.ledger.entries
|
|
171
|
+
.filter((e) => e.status === 'reserved' || e.status === 'committed')
|
|
172
|
+
.reduce((sum, e) => sum + e.amount, 0);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Parse a TTL string like "15m" or "2h" into seconds.
|
|
176
|
+
*/
|
|
177
|
+
static parseTtl(ttl) {
|
|
178
|
+
const match = ttl.match(/^(\d+)(s|m|h)$/);
|
|
179
|
+
if (!match)
|
|
180
|
+
throw new Error(`Invalid TTL format: ${ttl}`);
|
|
181
|
+
const value = parseInt(match[1], 10);
|
|
182
|
+
switch (match[2]) {
|
|
183
|
+
case 's': return value;
|
|
184
|
+
case 'm': return value * 60;
|
|
185
|
+
case 'h': return value * 3600;
|
|
186
|
+
default: throw new Error(`Invalid TTL unit: ${match[2]}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get the quote TTL deadline (unix timestamp).
|
|
191
|
+
*/
|
|
192
|
+
getQuoteDeadline() {
|
|
193
|
+
const ttlSeconds = PolicyEngine.parseTtl(this.policy.negotiation.quote_ttl);
|
|
194
|
+
return Math.floor(Date.now() / 1000) + ttlSeconds;
|
|
195
|
+
}
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// Budget Ledger Persistence
|
|
198
|
+
// ============================================================================
|
|
199
|
+
getLedgerPath() {
|
|
200
|
+
return (0, path_1.join)(this.actpDir, 'budget-ledger.json');
|
|
201
|
+
}
|
|
202
|
+
todayString() {
|
|
203
|
+
// UTC — daily budget resets at UTC midnight.
|
|
204
|
+
return new Date().toISOString().split('T')[0];
|
|
205
|
+
}
|
|
206
|
+
ensureLedgerCurrent() {
|
|
207
|
+
const today = this.todayString();
|
|
208
|
+
if (this.ledger.date !== today) {
|
|
209
|
+
this.ledger = { version: 1, date: today, entries: [] };
|
|
210
|
+
this.saveLedger();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
loadLedger() {
|
|
214
|
+
const path = this.getLedgerPath();
|
|
215
|
+
const today = this.todayString();
|
|
216
|
+
try {
|
|
217
|
+
if (!(0, fs_1.existsSync)(path)) {
|
|
218
|
+
return { version: 1, date: today, entries: [] };
|
|
219
|
+
}
|
|
220
|
+
const raw = JSON.parse((0, fs_1.readFileSync)(path, 'utf8'));
|
|
221
|
+
if (raw.version !== 1 || raw.date !== today) {
|
|
222
|
+
return { version: 1, date: today, entries: [] };
|
|
223
|
+
}
|
|
224
|
+
return raw;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return { version: 1, date: today, entries: [] };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
ensureDir() {
|
|
231
|
+
if ((0, fs_1.existsSync)(this.actpDir)) {
|
|
232
|
+
const stat = (0, fs_1.lstatSync)(this.actpDir);
|
|
233
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
234
|
+
throw new Error(`Security: ${this.actpDir} is not a real directory`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
(0, fs_1.mkdirSync)(this.actpDir, { recursive: true, mode: 0o700 });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
saveLedger() {
|
|
242
|
+
this.ensureDir();
|
|
243
|
+
const filePath = this.getLedgerPath();
|
|
244
|
+
// Guard against target file being a symlink
|
|
245
|
+
if ((0, fs_1.existsSync)(filePath)) {
|
|
246
|
+
const fileStat = (0, fs_1.lstatSync)(filePath);
|
|
247
|
+
if (fileStat.isSymbolicLink()) {
|
|
248
|
+
throw new Error(`Security: ${filePath} is a symlink — refusing to overwrite`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const tmpPath = filePath + '.tmp';
|
|
252
|
+
// Guard against tmp file being a symlink
|
|
253
|
+
if ((0, fs_1.existsSync)(tmpPath)) {
|
|
254
|
+
const tmpStat = (0, fs_1.lstatSync)(tmpPath);
|
|
255
|
+
if (tmpStat.isSymbolicLink()) {
|
|
256
|
+
throw new Error(`Security: ${tmpPath} is a symlink — refusing to write`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Atomic write
|
|
260
|
+
(0, fs_1.writeFileSync)(tmpPath, JSON.stringify(this.ledger, null, 2), { mode: 0o600 });
|
|
261
|
+
(0, fs_1.renameSync)(tmpPath, filePath);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
exports.PolicyEngine = PolicyEngine;
|
|
265
|
+
//# sourceMappingURL=PolicyEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PolicyEngine.js","sourceRoot":"","sources":["../../src/negotiation/PolicyEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionStore — Commerce session tracking and traceability.
|
|
3
|
+
*
|
|
4
|
+
* Every negotiation carries a canonical `commerce_session_id` (UUID).
|
|
5
|
+
* No createTransaction() is allowed without a session ID.
|
|
6
|
+
*
|
|
7
|
+
* Persisted to `.actp/sessions.json` using atomic writes.
|
|
8
|
+
*/
|
|
9
|
+
export interface SessionMapping {
|
|
10
|
+
commerce_session_id: string;
|
|
11
|
+
actp_tx_id?: string;
|
|
12
|
+
task: string;
|
|
13
|
+
candidates_tried: string[];
|
|
14
|
+
selected_provider?: string;
|
|
15
|
+
status: 'active' | 'committed' | 'completed' | 'failed' | 'cancelled';
|
|
16
|
+
attempts: number;
|
|
17
|
+
created_at: string;
|
|
18
|
+
updated_at: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class SessionStore {
|
|
21
|
+
private actpDir;
|
|
22
|
+
private sessions;
|
|
23
|
+
constructor(actpDir?: string);
|
|
24
|
+
/**
|
|
25
|
+
* Create a new commerce session.
|
|
26
|
+
*/
|
|
27
|
+
create(task: string): SessionMapping;
|
|
28
|
+
/**
|
|
29
|
+
* Get a session by ID.
|
|
30
|
+
*/
|
|
31
|
+
get(sessionId: string): SessionMapping | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Find a session by ACTP transaction ID.
|
|
34
|
+
*/
|
|
35
|
+
findByTxId(txId: string): SessionMapping | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Record a candidate attempt (provider tried).
|
|
38
|
+
*/
|
|
39
|
+
recordAttempt(sessionId: string, providerSlug: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Link a session to an ACTP transaction.
|
|
42
|
+
*/
|
|
43
|
+
linkTransaction(sessionId: string, txId: string, providerSlug: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Update session status.
|
|
46
|
+
*/
|
|
47
|
+
updateStatus(sessionId: string, status: SessionMapping['status']): void;
|
|
48
|
+
/**
|
|
49
|
+
* List all sessions, optionally filtered by status.
|
|
50
|
+
*/
|
|
51
|
+
list(status?: SessionMapping['status']): SessionMapping[];
|
|
52
|
+
private getFilePath;
|
|
53
|
+
private load;
|
|
54
|
+
private pruneOldSessions;
|
|
55
|
+
private save;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=SessionStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionStore.d.ts","sourceRoot":"","sources":["../../src/negotiation/SessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,MAAM,WAAW,cAAc;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAWD,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA8B;gBAElC,OAAO,CAAC,EAAE,MAAM;IAM5B;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAepC;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIlD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAOpD;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAY5D;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAW5E;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,IAAI;IASvE;;OAEG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,cAAc,EAAE;IAUzD,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,IAAI;IAgBZ,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,IAAI;CAwCb"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SessionStore — Commerce session tracking and traceability.
|
|
4
|
+
*
|
|
5
|
+
* Every negotiation carries a canonical `commerce_session_id` (UUID).
|
|
6
|
+
* No createTransaction() is allowed without a session ID.
|
|
7
|
+
*
|
|
8
|
+
* Persisted to `.actp/sessions.json` using atomic writes.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.SessionStore = void 0;
|
|
12
|
+
const crypto_1 = require("crypto");
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const path_1 = require("path");
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// SessionStore
|
|
17
|
+
// ============================================================================
|
|
18
|
+
class SessionStore {
|
|
19
|
+
constructor(actpDir) {
|
|
20
|
+
this.actpDir = actpDir ?? (process.env.ACTP_DIR || (0, path_1.join)(process.cwd(), '.actp'));
|
|
21
|
+
this.sessions = new Map();
|
|
22
|
+
this.load();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a new commerce session.
|
|
26
|
+
*/
|
|
27
|
+
create(task) {
|
|
28
|
+
const session = {
|
|
29
|
+
commerce_session_id: (0, crypto_1.randomUUID)(),
|
|
30
|
+
task,
|
|
31
|
+
candidates_tried: [],
|
|
32
|
+
status: 'active',
|
|
33
|
+
attempts: 0,
|
|
34
|
+
created_at: new Date().toISOString(),
|
|
35
|
+
updated_at: new Date().toISOString(),
|
|
36
|
+
};
|
|
37
|
+
this.sessions.set(session.commerce_session_id, session);
|
|
38
|
+
this.save();
|
|
39
|
+
return session;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a session by ID.
|
|
43
|
+
*/
|
|
44
|
+
get(sessionId) {
|
|
45
|
+
return this.sessions.get(sessionId);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Find a session by ACTP transaction ID.
|
|
49
|
+
*/
|
|
50
|
+
findByTxId(txId) {
|
|
51
|
+
for (const session of this.sessions.values()) {
|
|
52
|
+
if (session.actp_tx_id === txId)
|
|
53
|
+
return session;
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Record a candidate attempt (provider tried).
|
|
59
|
+
*/
|
|
60
|
+
recordAttempt(sessionId, providerSlug) {
|
|
61
|
+
const session = this.sessions.get(sessionId);
|
|
62
|
+
if (!session)
|
|
63
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
64
|
+
if (!session.candidates_tried.includes(providerSlug)) {
|
|
65
|
+
session.candidates_tried.push(providerSlug);
|
|
66
|
+
}
|
|
67
|
+
session.attempts++;
|
|
68
|
+
session.updated_at = new Date().toISOString();
|
|
69
|
+
this.save();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Link a session to an ACTP transaction.
|
|
73
|
+
*/
|
|
74
|
+
linkTransaction(sessionId, txId, providerSlug) {
|
|
75
|
+
const session = this.sessions.get(sessionId);
|
|
76
|
+
if (!session)
|
|
77
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
78
|
+
session.actp_tx_id = txId;
|
|
79
|
+
session.selected_provider = providerSlug;
|
|
80
|
+
session.status = 'committed';
|
|
81
|
+
session.updated_at = new Date().toISOString();
|
|
82
|
+
this.save();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Update session status.
|
|
86
|
+
*/
|
|
87
|
+
updateStatus(sessionId, status) {
|
|
88
|
+
const session = this.sessions.get(sessionId);
|
|
89
|
+
if (!session)
|
|
90
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
91
|
+
session.status = status;
|
|
92
|
+
session.updated_at = new Date().toISOString();
|
|
93
|
+
this.save();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* List all sessions, optionally filtered by status.
|
|
97
|
+
*/
|
|
98
|
+
list(status) {
|
|
99
|
+
const all = Array.from(this.sessions.values());
|
|
100
|
+
if (!status)
|
|
101
|
+
return all;
|
|
102
|
+
return all.filter((s) => s.status === status);
|
|
103
|
+
}
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Persistence
|
|
106
|
+
// ============================================================================
|
|
107
|
+
getFilePath() {
|
|
108
|
+
return (0, path_1.join)(this.actpDir, 'sessions.json');
|
|
109
|
+
}
|
|
110
|
+
load() {
|
|
111
|
+
const path = this.getFilePath();
|
|
112
|
+
try {
|
|
113
|
+
if (!(0, fs_1.existsSync)(path))
|
|
114
|
+
return;
|
|
115
|
+
const raw = JSON.parse((0, fs_1.readFileSync)(path, 'utf8'));
|
|
116
|
+
if (raw.version !== 1)
|
|
117
|
+
return;
|
|
118
|
+
for (const session of raw.sessions) {
|
|
119
|
+
this.sessions.set(session.commerce_session_id, session);
|
|
120
|
+
}
|
|
121
|
+
// Prune terminal sessions older than 30 days
|
|
122
|
+
this.pruneOldSessions();
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Corrupted file — start fresh
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
pruneOldSessions(maxAgeDays = 30) {
|
|
129
|
+
const cutoff = new Date();
|
|
130
|
+
cutoff.setDate(cutoff.getDate() - maxAgeDays);
|
|
131
|
+
const terminalStatuses = ['completed', 'failed', 'cancelled'];
|
|
132
|
+
let pruned = false;
|
|
133
|
+
for (const [id, session] of this.sessions) {
|
|
134
|
+
if (terminalStatuses.includes(session.status) && new Date(session.updated_at) < cutoff) {
|
|
135
|
+
this.sessions.delete(id);
|
|
136
|
+
pruned = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (pruned)
|
|
140
|
+
this.save();
|
|
141
|
+
}
|
|
142
|
+
save() {
|
|
143
|
+
// Ensure directory exists
|
|
144
|
+
if ((0, fs_1.existsSync)(this.actpDir)) {
|
|
145
|
+
const stat = (0, fs_1.lstatSync)(this.actpDir);
|
|
146
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
147
|
+
throw new Error(`Security: ${this.actpDir} is not a real directory`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
(0, fs_1.mkdirSync)(this.actpDir, { recursive: true, mode: 0o700 });
|
|
152
|
+
}
|
|
153
|
+
const data = {
|
|
154
|
+
version: 1,
|
|
155
|
+
sessions: Array.from(this.sessions.values()),
|
|
156
|
+
};
|
|
157
|
+
const filePath = this.getFilePath();
|
|
158
|
+
// Guard against target file being a symlink
|
|
159
|
+
if ((0, fs_1.existsSync)(filePath)) {
|
|
160
|
+
const fileStat = (0, fs_1.lstatSync)(filePath);
|
|
161
|
+
if (fileStat.isSymbolicLink()) {
|
|
162
|
+
throw new Error(`Security: ${filePath} is a symlink — refusing to overwrite`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const tmpPath = filePath + '.tmp';
|
|
166
|
+
// Guard against tmp file being a symlink
|
|
167
|
+
if ((0, fs_1.existsSync)(tmpPath)) {
|
|
168
|
+
const tmpStat = (0, fs_1.lstatSync)(tmpPath);
|
|
169
|
+
if (tmpStat.isSymbolicLink()) {
|
|
170
|
+
throw new Error(`Security: ${tmpPath} is a symlink — refusing to write`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Atomic write
|
|
174
|
+
(0, fs_1.writeFileSync)(tmpPath, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
175
|
+
(0, fs_1.renameSync)(tmpPath, filePath);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.SessionStore = SessionStore;
|
|
179
|
+
//# sourceMappingURL=SessionStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionStore.js","sourceRoot":"","sources":["../../src/negotiation/SessionStore.ts"],"names":[],"mappings":"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"}
|