@oracle-agent/oracle 0.35.31 → 0.35.34
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 +19 -1
- package/dist/agent-lifecycle.mjs +3 -3
- package/dist/agent-sessions.mjs +7 -7
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/desk-server.mjs +37 -37
- package/dist/bin/oracle-data-mcp.mjs +17 -17
- package/dist/bin/oracle-gateway.mjs +16 -16
- package/dist/bin/oracle-investigate.mjs +11 -0
- package/dist/bin/oracle-launch-radar-shadow.mjs +6 -6
- package/dist/bin/oracle-mev-arb-shadow.mjs +6 -6
- package/dist/bin/oracle-mev-shadow.mjs +6 -6
- package/dist/bin/oracle-public-server.mjs +5 -5
- package/dist/bin/oracle-route.mjs +22 -22
- package/dist/bin/oracle-scan.mjs +15 -15
- package/dist/cli/commands/agent-session.mjs +7 -7
- package/dist/cli/commands/auth.mjs +17 -16
- package/dist/cli/commands/chat.mjs +208 -198
- package/dist/cli/commands/context.mjs +6 -6
- package/dist/cli/commands/doctor.mjs +9 -9
- package/dist/cli/commands/eval.mjs +104 -95
- package/dist/cli/commands/farm.mjs +22 -22
- package/dist/cli/commands/follow.mjs +16 -16
- package/dist/cli/commands/harness.mjs +1 -1
- package/dist/cli/commands/lifecycle.mjs +6 -6
- package/dist/cli/commands/model.mjs +212 -202
- package/dist/cli/commands/quickstart.mjs +7 -7
- package/dist/cli/commands/receipt.mjs +12 -12
- package/dist/cli/commands/resolve.mjs +12 -12
- package/dist/cli/commands/setup.mjs +57 -56
- package/dist/cli/commands/sign.mjs +15 -13
- package/dist/cli/commands/signer.mjs +19 -19
- package/dist/cli/commands/snipe.mjs +11 -11
- package/dist/cli/commands/strategy.mjs +5 -5
- package/dist/cli/commands/swap.mjs +31 -31
- package/dist/cli/commands/venues.mjs +2 -2
- package/dist/context-graph.mjs +3 -3
- package/dist/data/desk-data.mjs +35 -35
- package/dist/data/names.mjs +3 -3
- package/dist/data/providers/farming.mjs +2 -2
- package/dist/data/providers/lp-destination-discovery.mjs +4 -4
- package/dist/index.mjs +49 -49
- package/dist/investigator/index.mjs +2 -0
- package/dist/launch-radar/index.mjs +5 -5
- package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
- package/dist/local-signer/index.mjs +3 -3
- package/dist/local-signer/runtime.mjs +19 -19
- package/dist/nft/universal-mint-router.mjs +4 -4
- package/dist/router/index.mjs +3 -3
- package/dist/router/prepare-bridge.mjs +2 -2
- package/dist/scanner/index.mjs +4 -4
- package/dist/strategy/index.mjs +3 -3
- package/dist/tui/standalone-client.mjs +77 -68
- package/package.json +3 -1
- package/public/eval-report.json +2 -2
- package/public/oracle-splash/index.html +2 -2
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -19,6 +19,24 @@ providers without printing credentials. Linux, Windows, and macOS apps are in be
|
|
|
19
19
|
The CLI, source, and desktop beta are public to everyone. Locals Only holders
|
|
20
20
|
receive a 0% Oracle integrator fee; the NFT does not gate product access.
|
|
21
21
|
|
|
22
|
+
The package also installs `oracle-investigate`, a bounded report-only forensic CLI:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
oracle-investigate --help
|
|
26
|
+
oracle-investigate capabilities
|
|
27
|
+
oracle-investigate wallet --family evm --address 0xabc... --chain-id 8453 --limit 20
|
|
28
|
+
oracle-investigate wallet --family evm --address 0xabc... --chain-id 8453 --include-opensea
|
|
29
|
+
oracle-investigate analyze --input ./components.json
|
|
30
|
+
oracle-investigate overlap --input ./opensea-snapshots.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Every successful investigator command emits one JSON document. It has no signer,
|
|
34
|
+
prepare, broadcast, arbitrary RPC URL, provider URL, key argument, fetch, transport,
|
|
35
|
+
or clock option. OpenSea v2 enrichment reads only `OPENSEA_API_KEY`, only after the
|
|
36
|
+
valueless `--include-opensea` opt-in, and never paginates. Offline `overlap` accepts
|
|
37
|
+
strict bounded snapshots and performs no fetch. Unsupported or incomplete coverage
|
|
38
|
+
stays explicit as `NOT_REQUESTED`, `UNAVAILABLE`, `PARTIAL`, or `UNKNOWN`.
|
|
39
|
+
|
|
22
40
|
Hyperliquid core perpetual orders use a 2 bps builder fee; HIP-3 and HIP-4 use 1 bps.
|
|
23
41
|
The private operator configuration, approval flow, wire units, and holder waiver are documented in
|
|
24
42
|
[Hyperliquid builder code](docs/hyperliquid-builder-code.md).
|
|
@@ -275,7 +293,7 @@ known answer. This matters: the canonical QuoterV2 address also has bytecode on
|
|
|
275
293
|
Base, but does not price that chain's pairs. A codesize check would have
|
|
276
294
|
allowlisted the wrong contract.
|
|
277
295
|
|
|
278
|
-
**
|
|
296
|
+
**127 provider modules** and **548 operations** in the read/quote catalog, covering **220 unique
|
|
279
297
|
protocols/venues** across EVM, Solana, and Bitcoin (115 EVM + cross-chain, 98
|
|
280
298
|
Solana venues backed by 101 verified Jupiter program IDs, 6 Bitcoin surfaces).
|
|
281
299
|
One module can cover many protocols: the Jupiter module alone routes 98 Solana
|
package/dist/agent-lifecycle.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createHash as
|
|
2
|
-
`,{encoding:"utf8",mode:384,flag:"wx"});let p=Q(s,
|
|
3
|
-
`,"utf8"),X(i)}catch(s){if(i!==void 0){H(i);try{ee(r)}catch{}}throw s?.code==="EEXIST"?t("state is locked by another writer","state-locked"):s}try{return n()}finally{try{H(i)}finally{ee(r)}}}function Se({path:e,schemaVersion:t,fail:n}){if(typeof e!="string"||e.length<1||e.length>4096)throw n("bounded state path required","invalid-path");if(typeof n!="function")throw new TypeError("fail factory required");let r=ge(e);we(ve(r),{recursive:!0,mode:448});let i=P(r,t,n);function s(){let f={schemaVersion:t,events:i.events};i={...f,stateHash:k(f)},rt(r,i,n)}function p({tenantId:f,recordType:b,recordId:N,operation:v,occurredAt:S,record:C,expectedRecordHash:V=null}){return it(r,n,()=>{if(i=P(r,t,n),(([...i.events].reverse().find(x=>x.record?.boundId===C?.boundId)??null)?.record?.recordHash??null)!==V)throw n("record changed concurrently; retry from current state","state-conflict");if(C&&typeof C.recordHash=="string"){let{recordHash:x,...F}=C;if(k(F)!==x)throw n("record hash is inconsistent","integrity-failed")}let $={sequence:i.events.length+1,previousEventHash:i.events.at(-1)?.eventHash??null,tenantId:f,recordType:b,recordId:N,operation:v,occurredAt:S,record:C},q=_({...$,eventHash:k($)});return i={...i,events:[...i.events,q]},s(),q})}return Object.freeze({append:p,events:()=>(i=P(r,t,n),i.events.map(f=>structuredClone(f))),verify:()=>{try{return i=P(r,t,n),{ok:!0,count:i.events.length,stateHash:i.stateHash}}catch(f){return{ok:!1,reason:f?.code||"integrity-failed"}}},path:r})}var at=Object.freeze([/(?:^|\s)Bearer\s+\S+/i,/-----BEGIN [A-Z ]*PRIVATE KEY-----/i,/\b(?:sk-|xprv|gh[pousr]_|github_pat_|AKIA|ASIA)[A-Za-z0-9_/-]{12,}\b/i,/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/,/\b(?:0x)?[0-9a-f]{64}\b/i,/(?<![1-9A-HJ-NP-Za-km-z])[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}(?![1-9A-HJ-NP-Za-km-z])/,/(?<![1-9A-HJ-NP-Za-km-z])[1-9A-HJ-NP-Za-km-z]{64,88}(?![1-9A-HJ-NP-Za-km-z])/]),st=new Set(["apikey","key","token","accesstoken","secret","password","passwd","auth","authorization","bearer","signertoken","credential","credentials","clientsecret","privatekey","xapikey","accesskey","refreshtoken"]),ct=Object.freeze(["apikey","accesskey","privatekey","clientsecret","accesstoken","refreshtoken","signertoken","credential","password","passwd","authorization","bearer","secret","token"]);function dt(e){return String(e??"").replace(/[^a-z0-9]/gi,"").toLowerCase()}function lt(e){let t;try{t=new URL(e)}catch{return!1}if(t.username||t.password)return!0;for(let n of t.searchParams.keys()){let r=dt(n);if(st.has(r)||ct.some(i=>r.includes(i)))return!0}return!1}function Ee(e){try{let t=decodeURIComponent(e);return t===e?null:t}catch{return null}}var ut=/[a-z][a-z0-9+.-]{1,15}(?::\/\/|%3a%2f%2f)\S+/gi;function ft(e){return e.replace(/[),.;:!?'"\]}]+$/,"")}function pt(e){let t=e.match(ut)||[];for(let n of t){let r=ft(n),i=Ee(r),s=i?Ee(i):null;for(let p of[r,i,s])if(p&<(p))return!0}return!1}function ne(e){return typeof e!="string"||e.length===0?!1:at.some(t=>t.test(e))?!0:pt(e)}var yt="oracle.agent-lifecycle/1",ht="oracle.agent-lifecycle-state/1",mt=Object.freeze(["agent","tool","workflow","credential"]),wt=Object.freeze(["active","quarantined","retired","pending_reactivation"]),U=Object.freeze({inactivityMs:2160*60*60*1e3,maxEvalAgeMs:720*60*60*1e3}),At=50,Ie=100,be=new Set(mt),Re=/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/,vt=512,Oe=300*1e3,gt=["authorization","apikey","accesskey","cookie","password","passphrase","secret","token","privatekey","seed","mnemonic","keystore","signature"],re=class extends Error{constructor(t,n="invalid-agent-lifecycle"){super(`agent-lifecycle: ${t}`),this.name="AgentLifecycleError",this.code=n}};function l(e,t){return new re(e,t)}function R(e,t){if(typeof e!="string")throw l(`${t} must be an ISO timestamp`,"invalid-time");let n=Date.parse(e);if(!Number.isFinite(n)||new Date(n).toISOString()!==e)throw l(`${t} must be an ISO timestamp`,"invalid-time");return e}function E(e,t){let n=String(e??"").trim();if(ne(n))throw l(`${t} contains secret-shaped material`,"secret-material");if(!Re.test(n))throw l(`${t} is invalid`,"invalid-id");return n}function L(e,t,{required:n=!0}={}){let r=String(e??"").trim();if(n&&!r||r.length>vt||/[\u0000-\u001f\u007f]/.test(r)||ne(r))throw l(`${t} is invalid or contains secret-shaped material`,"invalid-text");return r}function St(e={}){if(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)throw l("metadata must be a plain object","invalid-metadata");let t=Object.keys(e).sort();if(t.length>24)throw l("metadata field limit exceeded","metadata-limit");let n={};for(let r of t){if(!/^[A-Za-z][A-Za-z0-9_.-]{0,47}$/.test(r))throw l(`metadata key ${r} is invalid`,"invalid-metadata");let i=r.replace(/[^a-z0-9]/gi,"").toLowerCase();if(gt.some(p=>i.includes(p)))throw l(`metadata key ${r} is forbidden because it may contain a secret`,"secret-material");let s=e[r];if(typeof s=="string")n[r]=L(s,`metadata.${r}`,{required:!1});else if(typeof s=="boolean"||s===null)n[r]=s;else if(typeof s=="number"&&Number.isFinite(s))n[r]=s;else throw l(`metadata.${r} must be a scalar`,"invalid-metadata")}return n}function _e(e=[]){if(!Array.isArray(e)||e.length>32)throw l("credentialRefs must be a bounded array","invalid-credentials");let t=new Set;return e.map(n=>{if(!n||typeof n!="object"||Array.isArray(n))throw l("credential reference is invalid","invalid-credentials");let r=Object.keys(n).filter(s=>!["ref","expiresAt"].includes(s));if(r.length)throw l(`credential reference has unknown fields: ${r.sort().join(", ")}`,"invalid-credentials");let i=E(L(n.ref,"credential ref"),"credential ref");if(t.has(i))throw l("credential references must be unique","invalid-credentials");return t.add(i),{ref:i,expiresAt:R(n.expiresAt,"credential expiresAt")}}).sort((n,r)=>n.ref.localeCompare(r.ref))}function Et(e={}){let t=e.inactivityMs??U.inactivityMs,n=e.maxEvalAgeMs??U.maxEvalAgeMs;if(!Number.isSafeInteger(t)||t<1440*60*1e3||t>3660*24*60*60*1e3)throw l("policy.inactivityMs is invalid","invalid-policy");if(!Number.isSafeInteger(n)||n<1||n>3660*24*60*60*1e3)throw l("policy.maxEvalAgeMs is invalid","invalid-policy");return{inactivityMs:t,maxEvalAgeMs:n}}function Ne(e){let t=e==null||e===""?At:Number(e);if(!Number.isSafeInteger(t)||t<1||t>Ie)throw l(`limit must be an integer from 1 to ${Ie}`,"invalid-limit");return t}function Ce(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64url")}function It(e,t){if(typeof e!="string"||e.length<1||e.length>2048||!/^[A-Za-z0-9_-]+$/.test(e))throw l("cursor is invalid","invalid-cursor");let n;try{n=JSON.parse(Buffer.from(e,"base64url").toString("utf8"))}catch{throw l("cursor is invalid","invalid-cursor")}let r=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n).sort():[],i=["after","checkedAt","entityType","kind","sequence","status","tenantId","version"].sort();if(JSON.stringify(r)!==JSON.stringify(i)||n.version!==1||n.kind!==t.kind||n.tenantId!==t.tenantId||n.entityType!==t.entityType||n.status!==t.status||!Number.isSafeInteger(n.sequence)||n.sequence<0||n.sequence>t.headSequence||typeof n.after!="string"||!Re.test(n.after)||Ce(n)!==e)throw l("cursor does not match this lifecycle query","invalid-cursor");try{R(n.checkedAt,"cursor checkedAt")}catch{throw l("cursor is invalid","invalid-cursor")}if(Date.parse(n.checkedAt)>Date.parse(t.authorizedAt))throw l("cursor timestamp is in the future","invalid-cursor");return n}function Te(e){let t=new Map;for(let n of e)t.set(`${n.tenantId}\0${n.recordId}`,n.record);return t}function ke(e,{at:t=new Date().toISOString(),inactivityMs:n=U.inactivityMs,maxEvalAgeMs:r=U.maxEvalAgeMs}={}){let i=R(t,"at"),s=Date.parse(i),p=[];if(e.latestEval&&(e.latestEval.passed===!1||e.latestEval.score<e.latestEval.threshold)&&p.push("eval-below-threshold"),e.latestEval?.passed===!0&&s-Date.parse(e.latestEval.evaluatedAt)>r&&p.push("eval-stale"),(e.credentialRefs||[]).some(b=>Date.parse(b.expiresAt)<=s)&&p.push("credential-expired"),e.entityType==="credential"&&e.expiresAt&&Date.parse(e.expiresAt)<=s&&p.push("credential-expired"),p.length)return _({status:"quarantined",reasons:p.sort(),evaluatedAt:i});let f=e.lastUsedAt??e.registeredAt;return s-Date.parse(f)>=n?_({status:"retired",reasons:["inactive"],evaluatedAt:i}):_({status:"active",reasons:[],evaluatedAt:i})}function zt({path:e,now:t=()=>new Date().toISOString(),policy:n={}}={}){let r=Et(n),i=Se({path:e,schemaVersion:ht,fail:l});function s(){return R(t(),"now")}function p(o,y,u=s()){return he({context:o,resource:"lifecycle",action:y,decidedAt:u})}function f(o,y){return Te(i.events()).get(`${o.tenantId}\0${y}`)??null}function b({context:o,kind:y,cursor:u,checkedAt:c,entityType:d=null,status:a=null}){let h=i.events(),m=h.at(-1)?.sequence??0,A=u==null?null:It(u,{kind:y,tenantId:o.tenantId,entityType:d,status:a,headSequence:m,authorizedAt:c}),w=A?.sequence??m,g=A?.checkedAt??c,D=A?.after??null;return{records:[...Te(h.filter(I=>I.sequence<=w)).values()].filter(I=>I.tenantId===o.tenantId).filter(I=>d==null||I.entityType===d).sort((I,j)=>I.entityId.localeCompare(j.entityId)).filter(I=>D==null||I.entityId.localeCompare(D)>0),sequence:w,checkedAt:g}}function N({items:o,hasMore:y,lastEntityId:u,kind:c,context:d,entityType:a=null,status:h=null,sequence:m,checkedAt:A}){let w=y?Ce({version:1,kind:c,tenantId:d.tenantId,entityType:a,status:h,sequence:m,checkedAt:A,after:u}):null;return _({items:o,nextCursor:w,sequence:m})}function v(o,y){let u=ke(o,{at:y,...r}),c=["quarantined","retired","pending_reactivation"].includes(o.status)&&u.status==="active",d=c?o.status:u.status,a=c?[...o.reasons||[]]:[...u.reasons];return _({...structuredClone(o),status:d,reasons:a,evaluatedAt:u.evaluatedAt})}function S(o,y,u,c=s()){let d=u.recordHash??null,a={...u};delete a.recordHash;let h=_({...a,recordHash:k(a)});return i.append({tenantId:o.tenantId,recordType:"lifecycle",recordId:h.entityId,operation:y,occurredAt:c,record:h,expectedRecordHash:d}),h}function C({context:o,input:y}={}){let u=s();p(o,"create",u);let c=E(y?.entityId,"entityId");if(f(o,c))throw l("entity already exists","duplicate-entity");let d=String(y?.entityType??"").trim();if(!be.has(d))throw l("entityType is invalid","invalid-entity-type");let a=_e(y?.credentialRefs);if(d==="credential"&&a.length)throw l("credential entities cannot contain credentialRefs","invalid-credentials");let h=d==="credential"?R(y?.expiresAt,"expiresAt"):null,m=a.some(g=>Date.parse(g.expiresAt)<=Date.parse(u))||h!=null&&Date.parse(h)<=Date.parse(u),A=E(y?.ownerActorId,"ownerActorId"),w=E(o.actor.actorId,"registering actorId");if(!o.actor.roles.includes("owner")&&A!==w)throw l("only an owner may assign lifecycle ownership to another actor","owner-assignment-required");return S(o,"register",{schemaVersion:yt,tenantId:o.tenantId,boundId:ye(o,"lifecycle",c),entityId:c,entityType:d,label:L(y?.label,"label"),ownerActorId:A,registeredBy:w,credentialRefs:a,expiresAt:h,metadata:St(y?.metadata),status:m?"quarantined":"active",reasons:m?["credential-expired"]:[],registeredAt:u,updatedAt:u,lastUsedAt:null,latestEval:null,reactivation:null,revision:1},u)}function V({context:o,entityId:y}={}){let u=s();p(o,"read",u);let c=f(o,E(y,"entityId"));return c?v(c,u):null}function oe({context:o,entityType:y=null,status:u=null,limit:c=null,cursor:d=null}={}){let a=s();if(p(o,"read",a),y!=null&&!be.has(y))throw l("entityType is invalid","invalid-entity-type");if(u!=null&&!wt.includes(u))throw l("status is invalid","invalid-status");let h=Ne(c),m=b({context:o,kind:"list",cursor:d,checkedAt:a,entityType:y,status:u}),A=m.records.map(g=>v(g,m.checkedAt)).filter(g=>u==null||g.status===u),w=A.slice(0,h).map(g=>_(structuredClone(g)));return N({items:w,hasMore:A.length>h,lastEntityId:w.at(-1)?.entityId??null,kind:"list",context:o,entityType:y,status:u,sequence:m.sequence,checkedAt:m.checkedAt})}function ie({context:o,entityId:y,outcome:u,occurredAt:c=null}={}){let d=s();p(o,"update",d);let a=f(o,E(y,"entityId"));if(!a)throw l("entity not found","not-found");let h=new Set(["succeeded","failed","denied","cancelled","skipped"]),m=String(u??"").trim();if(!h.has(m))throw l("usage outcome is invalid","invalid-outcome");let A=R(c??d,"occurredAt"),w=v(a,d);if(w.status!=="active")throw(w.status!==a.status||JSON.stringify(w.reasons)!==JSON.stringify(a.reasons||[]))&&S(o,"usage-denied",{...a,status:w.status,reasons:[...w.reasons],evaluatedAt:w.evaluatedAt,updatedAt:d,revision:a.revision+1},d),l(`entity is not active: ${w.status}`,"entity-not-active");if(Date.parse(A)>Date.parse(d)+Oe)throw l("occurredAt is too far in the future","future-usage");if(a.lastUsedAt&&Date.parse(A)<Date.parse(a.lastUsedAt))throw l("occurredAt must be monotonic","non-monotonic-usage");return S(o,"usage",{...a,lastUsedAt:A,lastOutcome:m,updatedAt:d,revision:a.revision+1},d)}function $({context:o,entityId:y,suite:u,score:c,threshold:d,evaluatedAt:a=null}={}){let h=s();p(o,"update",h);let m=f(o,E(y,"entityId"));if(!m)throw l("entity not found","not-found");let A=Number(c),w=Number(d);if(![A,w].every(j=>Number.isFinite(j)&&j>=0&&j<=1))throw l("eval score and threshold must be from 0 to 1","invalid-eval");let g=R(a??h,"evaluatedAt");if(Date.parse(g)>Date.parse(h)+Oe)throw l("evaluatedAt is too far in the future","future-eval");if(m.latestEval&&Date.parse(g)<Date.parse(m.latestEval.evaluatedAt))throw l("evaluatedAt must be monotonic","non-monotonic-eval");let D={suite:E(u,"eval suite"),score:A,threshold:w,evaluatedAt:g,evaluatorActorId:E(o.actor.actorId,"evaluatorActorId"),passed:A>=w},ae={...m,latestEval:D},I=v(ae,h);return S(o,"eval",{...m,latestEval:D,status:I.status,reasons:[...I.reasons],evaluatedAt:I.evaluatedAt,updatedAt:h,revision:m.revision+1},h)}function q({context:o,entityId:y,refs:u}={}){let c=s();p(o,"update",c);let d=f(o,E(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=v(d,c);if(a.entityType==="credential")throw l("credential entities use updateCredentialExpiry","invalid-credentials");let h=_e(u),m=h.some(A=>Date.parse(A.expiresAt)<=Date.parse(c));return S(o,"credential-refs",{...a,credentialRefs:h,status:m?"quarantined":a.status,reasons:m?[...new Set([...a.reasons||[],"credential-expired"])].sort():a.reasons,updatedAt:c,revision:a.revision+1},c)}function x({context:o,entityId:y,expiresAt:u}={}){let c=s();p(o,"update",c);let d=f(o,E(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=v(d,c);if(a.entityType!=="credential")throw l("entity is not a credential","invalid-entity-type");let h=R(u,"expiresAt"),m=Date.parse(h)<=Date.parse(c);return S(o,"credential-expiry",{...a,expiresAt:h,status:m?"quarantined":a.status,reasons:m?[...new Set([...a.reasons||[],"credential-expired"])].sort():a.reasons,updatedAt:c,revision:a.revision+1},c)}function F({context:o,limit:y=null,cursor:u=null}={}){let c=s();p(o,"manage",c);let d=Ne(y),a=b({context:o,kind:"sweep",cursor:u,checkedAt:c}),h=a.checkedAt,m=[],A=a.records.slice(0,d);for(let w of A){let g=v(w,h);(g.status!==w.status||JSON.stringify(g.reasons)!==JSON.stringify(w.reasons||[]))&&S(o,"sweep",{...w,status:g.status,reasons:[...g.reasons],evaluatedAt:h,updatedAt:h,revision:w.revision+1},h),m.push({entityId:w.entityId,status:g.status,reasons:[...g.reasons],evaluatedAt:h})}return N({items:m.map(w=>_(w)),hasMore:a.records.length>d,lastEntityId:A.at(-1)?.entityId??null,kind:"sweep",context:o,sequence:a.sequence,checkedAt:h})}function xe({context:o,entityId:y,reason:u}={}){let c=s();p(o,"update",c);let d=f(o,E(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=v(d,c);if(!["quarantined","retired"].includes(a.status))throw l("only quarantined or retired entities may request reactivation","invalid-transition");return S(o,"reactivation-requested",{...a,status:"pending_reactivation",reactivation:{requestedAt:c,requestedBy:E(o.actor.actorId,"requestedBy"),reason:L(u,"reactivation reason"),reviewedAt:null,reviewedBy:null,review:null},updatedAt:c,revision:a.revision+1},c)}function De({context:o,entityId:y,review:u}={}){let c=s();p(o,"approve",c);let d=f(o,E(y,"entityId"));if(!d)throw l("entity not found","not-found");if(d.status!=="pending_reactivation"||!d.reactivation)throw l("reactivation request is required","invalid-transition");let a=ke(d,{at:c,...r});if(a.status!=="active")throw l(`reactivation remediation incomplete: ${a.reasons.join(", ")}`,"remediation-required");let h=c;return S(o,"reactivation-approved",{...d,status:"active",reasons:[],reactivation:{...d.reactivation,reviewedAt:h,reviewedBy:E(o.actor.actorId,"reviewedBy"),review:L(u,"reactivation review")},updatedAt:h,revision:d.revision+1},c)}return Object.freeze({register:C,get:V,list:oe,recordUsage:ie,recordEval:$,updateCredentialRefs:q,updateCredentialExpiry:x,sweep:F,requestReactivation:xe,approveReactivation:De,verify:i.verify})}export{mt as AGENT_LIFECYCLE_ENTITY_TYPES,yt as AGENT_LIFECYCLE_SCHEMA_VERSION,ht as AGENT_LIFECYCLE_STATE_VERSION,wt as AGENT_LIFECYCLE_STATUSES,re as AgentLifecycleError,At as DEFAULT_AGENT_LIFECYCLE_PAGE_LIMIT,U as DEFAULT_AGENT_LIFECYCLE_POLICY,Ie as MAX_AGENT_LIFECYCLE_PAGE_LIMIT,zt as createAgentLifecycleController,ke as evaluateLifecycleRecord};
|
|
1
|
+
import{createHash as ze}from"node:crypto";var De=1,Le=1,$e=1;var qe=Object.freeze(["owner","operator","agent","viewer"]),Me=Object.freeze(["tenant","config","policy","grant","workflow","trade","receipt","audit","telemetry","context","lifecycle"]),de=Object.freeze({read:"read",create:"create",update:"update",delete:"delete",manage:"manage",prepare:"prepare",cancel:"cancel",export:"export",approve:"approve"}),Pe=Object.freeze(["owner"]),O=Object.freeze({ALLOW_ROLE_PERMISSION:"allow.role_permission",DENY_MISSING_CONTEXT:"deny.missing_context",DENY_INVALID_CONTEXT:"deny.invalid_context",DENY_INVALID_REQUEST:"deny.invalid_request",DENY_UNKNOWN_RESOURCE:"deny.unknown_resource",DENY_UNKNOWN_ACTION:"deny.unknown_action",DENY_UNBOUND_OBJECT:"deny.unbound_object",DENY_TENANT_MISMATCH:"deny.tenant_mismatch",DENY_RESOURCE_MISMATCH:"deny.resource_mismatch",DENY_ROLE_PERMISSION:"deny.role_permission",DENY_POLICY_NOT_APPROVER:"deny.policy_not_approver"}),Ye=new Set(qe),Z=new Set(Me),Ue=new Set(Object.values(de)),He=new Set(["user","service","local-owner"]),Ve=new Set(["verified-session","service-credential","desktop-session","owner-arm-token","local-owner"]),B=/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,127}$/,le="tob1",Fe=new WeakSet;var ue=Object.freeze({owner:Object.freeze(["tenant:read","tenant:manage","config:read","config:manage","policy:read","policy:manage","grant:read","grant:create","grant:update","grant:delete","grant:manage","workflow:read","workflow:create","workflow:update","workflow:delete","workflow:cancel","workflow:approve","trade:read","trade:prepare","receipt:read","receipt:export","audit:read","audit:export","telemetry:read","telemetry:create","telemetry:export","context:read","context:create","context:update","context:delete","context:manage","context:export","lifecycle:read","lifecycle:create","lifecycle:update","lifecycle:delete","lifecycle:manage","lifecycle:approve","lifecycle:export"]),operator:Object.freeze(["tenant:read","config:read","policy:read","grant:read","workflow:read","workflow:create","workflow:update","workflow:cancel","trade:read","trade:prepare","receipt:read","audit:read","telemetry:read","telemetry:create","context:read","context:create","context:update","context:delete","lifecycle:read","lifecycle:create","lifecycle:update","lifecycle:manage"]),agent:Object.freeze(["tenant:read","config:read","policy:read","grant:read","workflow:read","workflow:create","workflow:update","trade:read","trade:prepare","receipt:read","telemetry:create","context:read","context:create","context:update","lifecycle:read"]),viewer:Object.freeze(["tenant:read","config:read","grant:read","workflow:read","trade:read","receipt:read","audit:read","telemetry:read","context:read","lifecycle:read"])}),Ot=Object.freeze(Object.fromEntries(Object.entries(ue).map(([e,t])=>[e,Object.freeze([...t])]))),x=class extends Error{constructor(t,n="invalid-context"){super(t),this.name="TenantContextError",this.code=n}};function se(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype}function K(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))K(t)}return e}function G(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(G).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${G(e[t])}`).join(",")}}`}function fe(e){return ze("sha256").update(G(e)).digest("hex")}function Je(e,t){return e.length===t.length&&e.every((n,r)=>n===t[r])}function Be(e){if(!se(e)||e.schemaVersion!==De||!B.test(e.tenantId||"")||typeof e.localCompatibility!="boolean")return!1;let t=e.actor;if(!se(t)||t.schemaVersion!==Le||!B.test(t.actorId||"")||!He.has(t.actorType)||!Ve.has(t.authSource)||!Array.isArray(t.roles)||t.roles.length===0)return!1;let n=[...new Set(t.roles)].sort();return n.every(r=>Ye.has(r))&&Je(n,t.roles)}function M(e){return Fe.has(e)&&Be(e)}function Ge(e){if(!M(e))throw new x("a resolved tenant context is required","unresolved-context");return e}function P(e){return Buffer.from(e,"utf8").toString("base64url")}function J(e,t){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))throw new x(`${t} binding is invalid`,"invalid-object-binding");let n=Buffer.from(e,"base64url").toString("utf8");if(!n||P(n)!==e)throw new x(`${t} binding is non-canonical`,"invalid-object-binding");return n}function pe(e){let t=String(e??"").trim();if(!t||t.length>256||/[\u0000-\u001f\u007f]/.test(t))throw new x("objectId is invalid","invalid-object-id");return t}function ye(e,t,n){Ge(e);let r=String(t??"").trim();if(!Z.has(r))throw new x("resource is unknown","unknown-resource");let i=pe(n);return`${le}.${P(e.tenantId)}.${P(r)}.${P(i)}`}function Ze(e){let t=String(e??""),n=t.split(".");if(n.length!==4||n[0]!==le)throw new x("tenant-bound object id required","unbound-object");let r=J(n[1],"tenant"),i=J(n[2],"resource"),s=J(n[3],"object");if(!B.test(r)||!Z.has(i))throw new x("tenant-bound object id is invalid","invalid-object-binding");return pe(s),K({schemaVersion:1,tenantId:r,resource:i,objectId:s,boundId:t})}function Ke(e){if(typeof e!="string"||!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(e))return null;let t=Date.parse(e);return Number.isFinite(t)&&new Date(t).toISOString()===e?e:null}function ce(e){let t={...e,decisionId:fe(e)};return K(t)}function We({context:e,resource:t,action:n,objectId:r=null,decidedAt:i}={}){let s=Ke(i),p={schemaVersion:$e,recordType:"tenant.access-decision",decidedAt:s,tenantId:M(e)?e.tenantId:null,actor:M(e)?{actorId:e.actor.actorId,actorType:e.actor.actorType,authSource:e.actor.authSource,roles:[...e.actor.roles]}:null,request:{resource:typeof t=="string"?t:null,action:typeof n=="string"?n:null,objectRefHash:r==null?null:fe(String(r))}},f=g=>ce({...p,allowed:!1,outcome:"deny",reason:g});if(e==null)return f(O.DENY_MISSING_CONTEXT);if(!M(e))return f(O.DENY_INVALID_CONTEXT);if(!s)return f(O.DENY_INVALID_REQUEST);if(!Z.has(t))return f(O.DENY_UNKNOWN_RESOURCE);if(!Ue.has(n))return f(O.DENY_UNKNOWN_ACTION);if(r!=null){let g;try{g=Ze(r)}catch{return f(O.DENY_UNBOUND_OBJECT)}if(g.tenantId!==e.tenantId)return f(O.DENY_TENANT_MISMATCH);if(g.resource!==t)return f(O.DENY_RESOURCE_MISMATCH)}if(n===de.approve&&!e.actor.roles.some(E=>Pe.includes(E)))return f(O.DENY_ROLE_PERMISSION);let b=`${t}:${n}`,N=e.actor.roles.some(g=>ue[g]?.includes(b));return ce({...p,allowed:N,outcome:N?"allow":"deny",reason:N?O.ALLOW_ROLE_PERMISSION:O.DENY_ROLE_PERMISSION})}function he(e){let t=We(e);if(!t.allowed){let n=new x(`tenant access denied: ${t.reason}`,"access-denied");throw n.decision=t,n}return t}import{createHash as Xe,randomUUID as Qe}from"node:crypto";import{chmodSync as et,closeSync as U,constants as D,existsSync as W,fsyncSync as X,lstatSync as me,mkdirSync as we,openSync as Q,readFileSync as tt,renameSync as nt,unlinkSync as ee,writeFileSync as Ae}from"node:fs";import{dirname as ge,resolve as ve}from"node:path";function te(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(te).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${te(e[t])}`).join(",")}}`}function T(e){return Xe("sha256").update(te(e)).digest("hex")}function _(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))_(t)}return e}function rt(e,t,n){let r=ve(e),i=ge(r);if(we(i,{recursive:!0,mode:448}),W(r)){let p=me(r);if(!p.isFile()||p.isSymbolicLink())throw n("state path must be a regular non-symlink file","unsafe-file")}let s=`${r}.${Qe()}.tmp`;try{Ae(s,`${JSON.stringify(t)}
|
|
2
|
+
`,{encoding:"utf8",mode:384,flag:"wx"});let p=Q(s,D.O_RDONLY);try{X(p)}finally{U(p)}nt(s,r),et(r,384);let f;try{f=Q(i,D.O_RDONLY),X(f)}finally{f!==void 0&&U(f)}}catch(p){try{W(s)&&ee(s)}catch{}throw p}}function ot(e,t,n){if(!e||typeof e!="object"||Array.isArray(e))throw n("state must be an object","integrity-failed");if(e.schemaVersion!==t||!Array.isArray(e.events))throw n("state schema is invalid","integrity-failed");let r=null;for(let p=0;p<e.events.length;p+=1){let f=e.events[p];if(!f||typeof f!="object"||Array.isArray(f))throw n("event is invalid","integrity-failed");if(f.record&&typeof f.record.recordHash=="string"){let{recordHash:g,...E}=f.record;if(T(E)!==g)throw n("record hash integrity failed; state may be tampered","integrity-failed")}let{eventHash:b,...N}=f;if(f.sequence!==p+1||f.previousEventHash!==r||T(N)!==b)throw n("event hash chain integrity failed; state may be tampered","integrity-failed");r=b}let{stateHash:i,...s}=e;if(T(s)!==i)throw n("state hash integrity failed; state may be tampered","integrity-failed");return e}function Y(e,t,n){if(!W(e)){let s={schemaVersion:t,events:[]};return{...s,stateHash:T(s)}}let r=me(e);if(!r.isFile()||r.isSymbolicLink())throw n("state path must be a regular non-symlink file","unsafe-file");if((r.mode&511)!==384)throw n("state file permissions must be 0600","unsafe-permissions");let i;try{i=JSON.parse(tt(e,"utf8"))}catch{throw n("state JSON is malformed","integrity-failed")}return ot(i,t,n)}function it(e,t,n){let r=`${e}.lock`,i;try{i=Q(r,D.O_CREAT|D.O_EXCL|D.O_WRONLY,384),Ae(i,`${JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})}
|
|
3
|
+
`,"utf8"),X(i)}catch(s){if(i!==void 0){U(i);try{ee(r)}catch{}}throw s?.code==="EEXIST"?t("state is locked by another writer","state-locked"):s}try{return n()}finally{try{U(i)}finally{ee(r)}}}function Ee({path:e,schemaVersion:t,fail:n}){if(typeof e!="string"||e.length<1||e.length>4096)throw n("bounded state path required","invalid-path");if(typeof n!="function")throw new TypeError("fail factory required");let r=ve(e);we(ge(r),{recursive:!0,mode:448});let i=Y(r,t,n);function s(){let f={schemaVersion:t,events:i.events};i={...f,stateHash:T(f)},rt(r,i,n)}function p({tenantId:f,recordType:b,recordId:N,operation:g,occurredAt:E,record:R,expectedRecordHash:V=null}){return it(r,n,()=>{if(i=Y(r,t,n),(([...i.events].reverse().find(C=>C.record?.boundId===R?.boundId)??null)?.record?.recordHash??null)!==V)throw n("record changed concurrently; retry from current state","state-conflict");if(R&&typeof R.recordHash=="string"){let{recordHash:C,...F}=R;if(T(F)!==C)throw n("record hash is inconsistent","integrity-failed")}let $={sequence:i.events.length+1,previousEventHash:i.events.at(-1)?.eventHash??null,tenantId:f,recordType:b,recordId:N,operation:g,occurredAt:E,record:R},q=_({...$,eventHash:T($)});return i={...i,events:[...i.events,q]},s(),q})}return Object.freeze({append:p,events:()=>(i=Y(r,t,n),i.events.map(f=>structuredClone(f))),verify:()=>{try{return i=Y(r,t,n),{ok:!0,count:i.events.length,stateHash:i.stateHash}}catch(f){return{ok:!1,reason:f?.code||"integrity-failed"}}},path:r})}var at=Object.freeze([/(?:^|\s)Bearer\s+\S+/i,/-----BEGIN [A-Z ]*PRIVATE KEY-----/i,/\b(?:sk-|xprv|gh[pousr]_|github_pat_|AKIA|ASIA)[A-Za-z0-9_/-]{12,}\b/i,/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/,/\b(?:0x)?[0-9a-f]{64}\b/i,/(?<![1-9A-HJ-NP-Za-km-z])[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}(?![1-9A-HJ-NP-Za-km-z])/,/(?<![1-9A-HJ-NP-Za-km-z])[1-9A-HJ-NP-Za-km-z]{64,88}(?![1-9A-HJ-NP-Za-km-z])/]),st=new Set(["apikey","key","token","accesstoken","secret","password","passwd","auth","authorization","bearer","signertoken","credential","credentials","clientsecret","privatekey","xapikey","accesskey","refreshtoken"]),ct=Object.freeze(["apikey","accesskey","privatekey","clientsecret","accesstoken","refreshtoken","signertoken","credential","password","passwd","authorization","bearer","secret","token"]);function dt(e){return String(e??"").replace(/[^a-z0-9]/gi,"").toLowerCase()}function lt(e){let t;try{t=new URL(e)}catch{return!1}if(t.username||t.password)return!0;for(let n of t.searchParams.keys()){let r=dt(n);if(st.has(r)||ct.some(i=>r.includes(i)))return!0}return!1}function Se(e){try{let t=decodeURIComponent(e);return t===e?null:t}catch{return null}}var ut=/[a-z][a-z0-9+.-]{1,15}(?::\/\/|%3a%2f%2f)\S+/gi;function ft(e){return e.replace(/[),.;:!?'"\]}]+$/,"")}function pt(e){let t=e.match(ut)||[];for(let n of t){let r=ft(n),i=Se(r),s=i?Se(i):null;for(let p of[r,i,s])if(p&<(p))return!0}return!1}var Rt=Object.freeze([Object.freeze([120,112,114,118]),Object.freeze([115,107,45]),Object.freeze([103,104,112,95]),Object.freeze([103,104,111,95]),Object.freeze([103,104,117,95]),Object.freeze([103,104,115,95]),Object.freeze([103,104,114,95]),Object.freeze([103,105,116,104,117,98,95,112,97,116,95]),Object.freeze([97,107,105,97]),Object.freeze([97,115,105,97])]);function ne(e){return typeof e!="string"||e.length===0?!1:at.some(t=>t.test(e))?!0:pt(e)}var yt="oracle.agent-lifecycle/1",ht="oracle.agent-lifecycle-state/1",mt=Object.freeze(["agent","tool","workflow","credential"]),wt=Object.freeze(["active","quarantined","retired","pending_reactivation"]),H=Object.freeze({inactivityMs:2160*60*60*1e3,maxEvalAgeMs:720*60*60*1e3}),At=50,Ie=100,be=new Set(mt),ke=/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/,gt=512,Oe=300*1e3,vt=["authorization","apikey","accesskey","cookie","password","passphrase","secret","token","privatekey","seed","mnemonic","keystore","signature"],re=class extends Error{constructor(t,n="invalid-agent-lifecycle"){super(`agent-lifecycle: ${t}`),this.name="AgentLifecycleError",this.code=n}};function l(e,t){return new re(e,t)}function k(e,t){if(typeof e!="string")throw l(`${t} must be an ISO timestamp`,"invalid-time");let n=Date.parse(e);if(!Number.isFinite(n)||new Date(n).toISOString()!==e)throw l(`${t} must be an ISO timestamp`,"invalid-time");return e}function S(e,t){let n=String(e??"").trim();if(ne(n))throw l(`${t} contains secret-shaped material`,"secret-material");if(!ke.test(n))throw l(`${t} is invalid`,"invalid-id");return n}function L(e,t,{required:n=!0}={}){let r=String(e??"").trim();if(n&&!r||r.length>gt||/[\u0000-\u001f\u007f]/.test(r)||ne(r))throw l(`${t} is invalid or contains secret-shaped material`,"invalid-text");return r}function Et(e={}){if(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)throw l("metadata must be a plain object","invalid-metadata");let t=Object.keys(e).sort();if(t.length>24)throw l("metadata field limit exceeded","metadata-limit");let n={};for(let r of t){if(!/^[A-Za-z][A-Za-z0-9_.-]{0,47}$/.test(r))throw l(`metadata key ${r} is invalid`,"invalid-metadata");let i=r.replace(/[^a-z0-9]/gi,"").toLowerCase();if(vt.some(p=>i.includes(p)))throw l(`metadata key ${r} is forbidden because it may contain a secret`,"secret-material");let s=e[r];if(typeof s=="string")n[r]=L(s,`metadata.${r}`,{required:!1});else if(typeof s=="boolean"||s===null)n[r]=s;else if(typeof s=="number"&&Number.isFinite(s))n[r]=s;else throw l(`metadata.${r} must be a scalar`,"invalid-metadata")}return n}function _e(e=[]){if(!Array.isArray(e)||e.length>32)throw l("credentialRefs must be a bounded array","invalid-credentials");let t=new Set;return e.map(n=>{if(!n||typeof n!="object"||Array.isArray(n))throw l("credential reference is invalid","invalid-credentials");let r=Object.keys(n).filter(s=>!["ref","expiresAt"].includes(s));if(r.length)throw l(`credential reference has unknown fields: ${r.sort().join(", ")}`,"invalid-credentials");let i=S(L(n.ref,"credential ref"),"credential ref");if(t.has(i))throw l("credential references must be unique","invalid-credentials");return t.add(i),{ref:i,expiresAt:k(n.expiresAt,"credential expiresAt")}}).sort((n,r)=>n.ref.localeCompare(r.ref))}function St(e={}){let t=e.inactivityMs??H.inactivityMs,n=e.maxEvalAgeMs??H.maxEvalAgeMs;if(!Number.isSafeInteger(t)||t<1440*60*1e3||t>3660*24*60*60*1e3)throw l("policy.inactivityMs is invalid","invalid-policy");if(!Number.isSafeInteger(n)||n<1||n>3660*24*60*60*1e3)throw l("policy.maxEvalAgeMs is invalid","invalid-policy");return{inactivityMs:t,maxEvalAgeMs:n}}function Ne(e){let t=e==null||e===""?At:Number(e);if(!Number.isSafeInteger(t)||t<1||t>Ie)throw l(`limit must be an integer from 1 to ${Ie}`,"invalid-limit");return t}function Re(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64url")}function It(e,t){if(typeof e!="string"||e.length<1||e.length>2048||!/^[A-Za-z0-9_-]+$/.test(e))throw l("cursor is invalid","invalid-cursor");let n;try{n=JSON.parse(Buffer.from(e,"base64url").toString("utf8"))}catch{throw l("cursor is invalid","invalid-cursor")}let r=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n).sort():[],i=["after","checkedAt","entityType","kind","sequence","status","tenantId","version"].sort();if(JSON.stringify(r)!==JSON.stringify(i)||n.version!==1||n.kind!==t.kind||n.tenantId!==t.tenantId||n.entityType!==t.entityType||n.status!==t.status||!Number.isSafeInteger(n.sequence)||n.sequence<0||n.sequence>t.headSequence||typeof n.after!="string"||!ke.test(n.after)||Re(n)!==e)throw l("cursor does not match this lifecycle query","invalid-cursor");try{k(n.checkedAt,"cursor checkedAt")}catch{throw l("cursor is invalid","invalid-cursor")}if(Date.parse(n.checkedAt)>Date.parse(t.authorizedAt))throw l("cursor timestamp is in the future","invalid-cursor");return n}function xe(e){let t=new Map;for(let n of e)t.set(`${n.tenantId}\0${n.recordId}`,n.record);return t}function Te(e,{at:t=new Date().toISOString(),inactivityMs:n=H.inactivityMs,maxEvalAgeMs:r=H.maxEvalAgeMs}={}){let i=k(t,"at"),s=Date.parse(i),p=[];if(e.latestEval&&(e.latestEval.passed===!1||e.latestEval.score<e.latestEval.threshold)&&p.push("eval-below-threshold"),e.latestEval?.passed===!0&&s-Date.parse(e.latestEval.evaluatedAt)>r&&p.push("eval-stale"),(e.credentialRefs||[]).some(b=>Date.parse(b.expiresAt)<=s)&&p.push("credential-expired"),e.entityType==="credential"&&e.expiresAt&&Date.parse(e.expiresAt)<=s&&p.push("credential-expired"),p.length)return _({status:"quarantined",reasons:p.sort(),evaluatedAt:i});let f=e.lastUsedAt??e.registeredAt;return s-Date.parse(f)>=n?_({status:"retired",reasons:["inactive"],evaluatedAt:i}):_({status:"active",reasons:[],evaluatedAt:i})}function Lt({path:e,now:t=()=>new Date().toISOString(),policy:n={}}={}){let r=St(n),i=Ee({path:e,schemaVersion:ht,fail:l});function s(){return k(t(),"now")}function p(o,y,u=s()){return he({context:o,resource:"lifecycle",action:y,decidedAt:u})}function f(o,y){return xe(i.events()).get(`${o.tenantId}\0${y}`)??null}function b({context:o,kind:y,cursor:u,checkedAt:c,entityType:d=null,status:a=null}){let h=i.events(),m=h.at(-1)?.sequence??0,A=u==null?null:It(u,{kind:y,tenantId:o.tenantId,entityType:d,status:a,headSequence:m,authorizedAt:c}),w=A?.sequence??m,v=A?.checkedAt??c,j=A?.after??null;return{records:[...xe(h.filter(I=>I.sequence<=w)).values()].filter(I=>I.tenantId===o.tenantId).filter(I=>d==null||I.entityType===d).sort((I,z)=>I.entityId.localeCompare(z.entityId)).filter(I=>j==null||I.entityId.localeCompare(j)>0),sequence:w,checkedAt:v}}function N({items:o,hasMore:y,lastEntityId:u,kind:c,context:d,entityType:a=null,status:h=null,sequence:m,checkedAt:A}){let w=y?Re({version:1,kind:c,tenantId:d.tenantId,entityType:a,status:h,sequence:m,checkedAt:A,after:u}):null;return _({items:o,nextCursor:w,sequence:m})}function g(o,y){let u=Te(o,{at:y,...r}),c=["quarantined","retired","pending_reactivation"].includes(o.status)&&u.status==="active",d=c?o.status:u.status,a=c?[...o.reasons||[]]:[...u.reasons];return _({...structuredClone(o),status:d,reasons:a,evaluatedAt:u.evaluatedAt})}function E(o,y,u,c=s()){let d=u.recordHash??null,a={...u};delete a.recordHash;let h=_({...a,recordHash:T(a)});return i.append({tenantId:o.tenantId,recordType:"lifecycle",recordId:h.entityId,operation:y,occurredAt:c,record:h,expectedRecordHash:d}),h}function R({context:o,input:y}={}){let u=s();p(o,"create",u);let c=S(y?.entityId,"entityId");if(f(o,c))throw l("entity already exists","duplicate-entity");let d=String(y?.entityType??"").trim();if(!be.has(d))throw l("entityType is invalid","invalid-entity-type");let a=_e(y?.credentialRefs);if(d==="credential"&&a.length)throw l("credential entities cannot contain credentialRefs","invalid-credentials");let h=d==="credential"?k(y?.expiresAt,"expiresAt"):null,m=a.some(v=>Date.parse(v.expiresAt)<=Date.parse(u))||h!=null&&Date.parse(h)<=Date.parse(u),A=S(y?.ownerActorId,"ownerActorId"),w=S(o.actor.actorId,"registering actorId");if(!o.actor.roles.includes("owner")&&A!==w)throw l("only an owner may assign lifecycle ownership to another actor","owner-assignment-required");return E(o,"register",{schemaVersion:yt,tenantId:o.tenantId,boundId:ye(o,"lifecycle",c),entityId:c,entityType:d,label:L(y?.label,"label"),ownerActorId:A,registeredBy:w,credentialRefs:a,expiresAt:h,metadata:Et(y?.metadata),status:m?"quarantined":"active",reasons:m?["credential-expired"]:[],registeredAt:u,updatedAt:u,lastUsedAt:null,latestEval:null,reactivation:null,revision:1},u)}function V({context:o,entityId:y}={}){let u=s();p(o,"read",u);let c=f(o,S(y,"entityId"));return c?g(c,u):null}function oe({context:o,entityType:y=null,status:u=null,limit:c=null,cursor:d=null}={}){let a=s();if(p(o,"read",a),y!=null&&!be.has(y))throw l("entityType is invalid","invalid-entity-type");if(u!=null&&!wt.includes(u))throw l("status is invalid","invalid-status");let h=Ne(c),m=b({context:o,kind:"list",cursor:d,checkedAt:a,entityType:y,status:u}),A=m.records.map(v=>g(v,m.checkedAt)).filter(v=>u==null||v.status===u),w=A.slice(0,h).map(v=>_(structuredClone(v)));return N({items:w,hasMore:A.length>h,lastEntityId:w.at(-1)?.entityId??null,kind:"list",context:o,entityType:y,status:u,sequence:m.sequence,checkedAt:m.checkedAt})}function ie({context:o,entityId:y,outcome:u,occurredAt:c=null}={}){let d=s();p(o,"update",d);let a=f(o,S(y,"entityId"));if(!a)throw l("entity not found","not-found");let h=new Set(["succeeded","failed","denied","cancelled","skipped"]),m=String(u??"").trim();if(!h.has(m))throw l("usage outcome is invalid","invalid-outcome");let A=k(c??d,"occurredAt"),w=g(a,d);if(w.status!=="active")throw(w.status!==a.status||JSON.stringify(w.reasons)!==JSON.stringify(a.reasons||[]))&&E(o,"usage-denied",{...a,status:w.status,reasons:[...w.reasons],evaluatedAt:w.evaluatedAt,updatedAt:d,revision:a.revision+1},d),l(`entity is not active: ${w.status}`,"entity-not-active");if(Date.parse(A)>Date.parse(d)+Oe)throw l("occurredAt is too far in the future","future-usage");if(a.lastUsedAt&&Date.parse(A)<Date.parse(a.lastUsedAt))throw l("occurredAt must be monotonic","non-monotonic-usage");return E(o,"usage",{...a,lastUsedAt:A,lastOutcome:m,updatedAt:d,revision:a.revision+1},d)}function $({context:o,entityId:y,suite:u,score:c,threshold:d,evaluatedAt:a=null}={}){let h=s();p(o,"update",h);let m=f(o,S(y,"entityId"));if(!m)throw l("entity not found","not-found");let A=Number(c),w=Number(d);if(![A,w].every(z=>Number.isFinite(z)&&z>=0&&z<=1))throw l("eval score and threshold must be from 0 to 1","invalid-eval");let v=k(a??h,"evaluatedAt");if(Date.parse(v)>Date.parse(h)+Oe)throw l("evaluatedAt is too far in the future","future-eval");if(m.latestEval&&Date.parse(v)<Date.parse(m.latestEval.evaluatedAt))throw l("evaluatedAt must be monotonic","non-monotonic-eval");let j={suite:S(u,"eval suite"),score:A,threshold:w,evaluatedAt:v,evaluatorActorId:S(o.actor.actorId,"evaluatorActorId"),passed:A>=w},ae={...m,latestEval:j},I=g(ae,h);return E(o,"eval",{...m,latestEval:j,status:I.status,reasons:[...I.reasons],evaluatedAt:I.evaluatedAt,updatedAt:h,revision:m.revision+1},h)}function q({context:o,entityId:y,refs:u}={}){let c=s();p(o,"update",c);let d=f(o,S(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=g(d,c);if(a.entityType==="credential")throw l("credential entities use updateCredentialExpiry","invalid-credentials");let h=_e(u),m=h.some(A=>Date.parse(A.expiresAt)<=Date.parse(c));return E(o,"credential-refs",{...a,credentialRefs:h,status:m?"quarantined":a.status,reasons:m?[...new Set([...a.reasons||[],"credential-expired"])].sort():a.reasons,updatedAt:c,revision:a.revision+1},c)}function C({context:o,entityId:y,expiresAt:u}={}){let c=s();p(o,"update",c);let d=f(o,S(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=g(d,c);if(a.entityType!=="credential")throw l("entity is not a credential","invalid-entity-type");let h=k(u,"expiresAt"),m=Date.parse(h)<=Date.parse(c);return E(o,"credential-expiry",{...a,expiresAt:h,status:m?"quarantined":a.status,reasons:m?[...new Set([...a.reasons||[],"credential-expired"])].sort():a.reasons,updatedAt:c,revision:a.revision+1},c)}function F({context:o,limit:y=null,cursor:u=null}={}){let c=s();p(o,"manage",c);let d=Ne(y),a=b({context:o,kind:"sweep",cursor:u,checkedAt:c}),h=a.checkedAt,m=[],A=a.records.slice(0,d);for(let w of A){let v=g(w,h);(v.status!==w.status||JSON.stringify(v.reasons)!==JSON.stringify(w.reasons||[]))&&E(o,"sweep",{...w,status:v.status,reasons:[...v.reasons],evaluatedAt:h,updatedAt:h,revision:w.revision+1},h),m.push({entityId:w.entityId,status:v.status,reasons:[...v.reasons],evaluatedAt:h})}return N({items:m.map(w=>_(w)),hasMore:a.records.length>d,lastEntityId:A.at(-1)?.entityId??null,kind:"sweep",context:o,sequence:a.sequence,checkedAt:h})}function Ce({context:o,entityId:y,reason:u}={}){let c=s();p(o,"update",c);let d=f(o,S(y,"entityId"));if(!d)throw l("entity not found","not-found");let a=g(d,c);if(!["quarantined","retired"].includes(a.status))throw l("only quarantined or retired entities may request reactivation","invalid-transition");return E(o,"reactivation-requested",{...a,status:"pending_reactivation",reactivation:{requestedAt:c,requestedBy:S(o.actor.actorId,"requestedBy"),reason:L(u,"reactivation reason"),reviewedAt:null,reviewedBy:null,review:null},updatedAt:c,revision:a.revision+1},c)}function je({context:o,entityId:y,review:u}={}){let c=s();p(o,"approve",c);let d=f(o,S(y,"entityId"));if(!d)throw l("entity not found","not-found");if(d.status!=="pending_reactivation"||!d.reactivation)throw l("reactivation request is required","invalid-transition");let a=Te(d,{at:c,...r});if(a.status!=="active")throw l(`reactivation remediation incomplete: ${a.reasons.join(", ")}`,"remediation-required");let h=c;return E(o,"reactivation-approved",{...d,status:"active",reasons:[],reactivation:{...d.reactivation,reviewedAt:h,reviewedBy:S(o.actor.actorId,"reviewedBy"),review:L(u,"reactivation review")},updatedAt:h,revision:d.revision+1},c)}return Object.freeze({register:R,get:V,list:oe,recordUsage:ie,recordEval:$,updateCredentialRefs:q,updateCredentialExpiry:C,sweep:F,requestReactivation:Ce,approveReactivation:je,verify:i.verify})}export{mt as AGENT_LIFECYCLE_ENTITY_TYPES,yt as AGENT_LIFECYCLE_SCHEMA_VERSION,ht as AGENT_LIFECYCLE_STATE_VERSION,wt as AGENT_LIFECYCLE_STATUSES,re as AgentLifecycleError,At as DEFAULT_AGENT_LIFECYCLE_PAGE_LIMIT,H as DEFAULT_AGENT_LIFECYCLE_POLICY,Ie as MAX_AGENT_LIFECYCLE_PAGE_LIMIT,Lt as createAgentLifecycleController,Te as evaluateLifecycleRecord};
|