@oracle-agent/oracle 0.35.31 → 0.35.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +19 -1
  2. package/dist/agent-lifecycle.mjs +3 -3
  3. package/dist/agent-sessions.mjs +7 -7
  4. package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
  5. package/dist/bin/desk-server.mjs +37 -37
  6. package/dist/bin/oracle-data-mcp.mjs +17 -17
  7. package/dist/bin/oracle-gateway.mjs +16 -16
  8. package/dist/bin/oracle-investigate.mjs +11 -0
  9. package/dist/bin/oracle-launch-radar-shadow.mjs +6 -6
  10. package/dist/bin/oracle-mev-arb-shadow.mjs +6 -6
  11. package/dist/bin/oracle-mev-shadow.mjs +6 -6
  12. package/dist/bin/oracle-public-server.mjs +5 -5
  13. package/dist/bin/oracle-route.mjs +22 -22
  14. package/dist/bin/oracle-scan.mjs +15 -15
  15. package/dist/cli/commands/agent-session.mjs +7 -7
  16. package/dist/cli/commands/chat.mjs +197 -197
  17. package/dist/cli/commands/context.mjs +6 -6
  18. package/dist/cli/commands/doctor.mjs +9 -9
  19. package/dist/cli/commands/eval.mjs +50 -50
  20. package/dist/cli/commands/farm.mjs +22 -22
  21. package/dist/cli/commands/follow.mjs +16 -16
  22. package/dist/cli/commands/lifecycle.mjs +6 -6
  23. package/dist/cli/commands/model.mjs +201 -201
  24. package/dist/cli/commands/quickstart.mjs +7 -7
  25. package/dist/cli/commands/receipt.mjs +12 -12
  26. package/dist/cli/commands/resolve.mjs +12 -12
  27. package/dist/cli/commands/sign.mjs +15 -13
  28. package/dist/cli/commands/signer.mjs +19 -19
  29. package/dist/cli/commands/snipe.mjs +11 -11
  30. package/dist/cli/commands/strategy.mjs +5 -5
  31. package/dist/cli/commands/swap.mjs +31 -31
  32. package/dist/cli/commands/venues.mjs +2 -2
  33. package/dist/context-graph.mjs +3 -3
  34. package/dist/data/desk-data.mjs +35 -35
  35. package/dist/data/names.mjs +3 -3
  36. package/dist/data/providers/farming.mjs +2 -2
  37. package/dist/data/providers/lp-destination-discovery.mjs +4 -4
  38. package/dist/index.mjs +49 -49
  39. package/dist/investigator/index.mjs +2 -0
  40. package/dist/launch-radar/index.mjs +5 -5
  41. package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
  42. package/dist/local-signer/index.mjs +3 -3
  43. package/dist/local-signer/runtime.mjs +19 -19
  44. package/dist/nft/universal-mint-router.mjs +4 -4
  45. package/dist/router/index.mjs +3 -3
  46. package/dist/router/prepare-bridge.mjs +2 -2
  47. package/dist/scanner/index.mjs +4 -4
  48. package/dist/strategy/index.mjs +3 -3
  49. package/dist/tui/standalone-client.mjs +33 -33
  50. package/package.json +3 -1
  51. package/public/eval-report.json +2 -2
  52. package/public/oracle-splash/index.html +2 -2
  53. package/server.json +2 -2
@@ -1,6 +1,6 @@
1
- import{readFileSync as Je}from"node:fs";import{homedir as Ct}from"node:os";import{join as jt}from"node:path";import{createHash as Ge}from"node:crypto";var U=1,V=1,Ze=1,le="local-owner",ue="local-owner",Xe=Object.freeze(["owner","operator","agent","viewer"]),Be=Object.freeze(["tenant","config","policy","grant","workflow","trade","receipt","audit","telemetry","context","lifecycle"]),ye=Object.freeze({read:"read",create:"create",update:"update",delete:"delete",manage:"manage",prepare:"prepare",cancel:"cancel",export:"export",approve:"approve"}),We=Object.freeze(["owner"]),N=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"}),ge=new Set(Xe),Q=new Set(Be),Ke=new Set(Object.values(ye)),we=new Set(["user","service","local-owner"]),Se=new Set(["verified-session","service-credential","desktop-session","owner-arm-token","local-owner"]),q=/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,127}$/,Ie="tob1",be=new WeakSet,Ae=new WeakMap,Ne=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"])}),Ht=Object.freeze(Object.fromEntries(Object.entries(Ne).map(([e,t])=>[e,Object.freeze([...t])]))),g=class extends Error{constructor(t,n="invalid-context"){super(t),this.name="TenantContextError",this.code=n}};function W(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype}function J(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))J(t)}return e}function K(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(K).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${K(e[t])}`).join(",")}}`}function Ee(e){return Ge("sha256").update(K(e)).digest("hex")}function fe(e,t,n){if(!W(e))throw new g(`${n} must be a plain object`);let r=Object.keys(e).filter(o=>!t.has(o));if(r.length)throw new g(`${n} has unknown fields: ${r.sort().join(", ")}`)}function pe(e,t){let n=String(e??"").trim();if(!q.test(n))throw new g(`${t} is invalid`);return n}function me(e,t="assignedRoles"){if(!Array.isArray(e)||e.length===0)throw new g(`${t} must contain at least one trusted role`,"missing-role-assignment");let n=[...new Set(e.map(o=>String(o??"").trim()))].sort(),r=n.filter(o=>!ge.has(o));if(r.length)throw new g(`${t} contains unknown roles: ${r.join(", ")}`,"unknown-role");return n}function Oe(e,t){return e.length===t.length&&e.every((n,r)=>n===t[r])}function Qe(e){if(!W(e)||e.schemaVersion!==U||!q.test(e.tenantId||"")||typeof e.localCompatibility!="boolean")return!1;let t=e.actor;if(!W(t)||t.schemaVersion!==V||!q.test(t.actorId||"")||!we.has(t.actorType)||!Se.has(t.authSource)||!Array.isArray(t.roles)||t.roles.length===0)return!1;let n=[...new Set(t.roles)].sort();return n.every(r=>ge.has(r))&&Oe(n,t.roles)}function et(e,{assignedTenantId:t,assignedActorId:n,assignedActorType:r,assignedAuthSource:o,assignedRoles:s,assignedContextDomains:c=null,localCompatibility:p=!1}={}){let I=e;if(fe(I,new Set(["schemaVersion","tenantId","actor","localCompatibility"]),"tenant claims"),I.schemaVersion!=null&&I.schemaVersion!==U)throw new g("unsupported tenant context schema version","unsupported-version");if(![t,n,r,o].every(f=>f!=null))throw new g("trusted tenant and actor identity assignments are required","missing-trusted-identity");let b=I.actor??{};if(fe(b,new Set(["schemaVersion","actorId","actorType","authSource","roles"]),"actor claims"),b.schemaVersion!=null&&b.schemaVersion!==V)throw new g("unsupported actor identity schema version","unsupported-version");let _=pe(t,"tenantId"),C=pe(n,"actorId"),j=String(r).trim(),i=String(o).trim();if(!we.has(j))throw new g("actorType is invalid");if(!Se.has(i))throw new g("authSource is invalid");let u=me(s);if(!Array.isArray(c)&&c!=null)throw new g("assignedContextDomains must be an array","invalid-domain-assignment");let d=c==null?u.includes("owner")?["*"]:[]:[...new Set(c.map(f=>String(f??"").trim()))].sort();if(d.some(f=>f!=="*"&&!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(f)))throw new g("assignedContextDomains contains an invalid domain","invalid-domain-assignment");if(b.roles!==void 0){let f;try{f=me(b.roles,"claimed roles")}catch{throw new g("claimed roles do not match the trusted assignment","forged-role")}if(!Oe(f,u))throw new g("claimed roles do not match the trusted assignment","forged-role")}if(I.localCompatibility!==void 0&&I.localCompatibility!==p)throw new g("local compatibility may only be set by the trusted boundary","forged-local-compatibility");if([[I.tenantId,_],[b.actorId,C],[b.actorType,j],[b.authSource,i]].some(([f,y])=>f!==void 0&&String(f).trim()!==y))throw new g("claimed identity does not match the trusted assignment","forged-identity");let l=J({schemaVersion:U,tenantId:_,actor:{schemaVersion:V,actorId:C,actorType:j,authSource:i,roles:u},localCompatibility:p===!0});return be.add(l),Ae.set(l,Object.freeze(d)),l}function ee(e,t){H(e);let n=String(t??"").trim();if(!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(n))return!1;let r=Ae.get(e)||[];return r.includes("*")||r.includes(n)}function F(e,t){if(!ee(e,t))throw new g("context domain access denied","domain-access-denied");return t}function _e({authSource:e="local-owner"}={}){if(!new Set(["local-owner","desktop-session","owner-arm-token"]).has(e))throw new g("local owner authSource is invalid");return et({schemaVersion:U,tenantId:le,actor:{schemaVersion:V,actorId:ue,actorType:"local-owner",authSource:e}},{assignedTenantId:le,assignedActorId:ue,assignedActorType:"local-owner",assignedAuthSource:e,assignedRoles:["owner"],localCompatibility:!0})}function M(e){return be.has(e)&&Qe(e)}function H(e){if(!M(e))throw new g("a resolved tenant context is required","unresolved-context");return e}function Y(e){return Buffer.from(e,"utf8").toString("base64url")}function B(e,t){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))throw new g(`${t} binding is invalid`,"invalid-object-binding");let n=Buffer.from(e,"base64url").toString("utf8");if(!n||Y(n)!==e)throw new g(`${t} binding is non-canonical`,"invalid-object-binding");return n}function Te(e){let t=String(e??"").trim();if(!t||t.length>256||/[\u0000-\u001f\u007f]/.test(t))throw new g("objectId is invalid","invalid-object-id");return t}function te(e,t,n){H(e);let r=String(t??"").trim();if(!Q.has(r))throw new g("resource is unknown","unknown-resource");let o=Te(n);return`${Ie}.${Y(e.tenantId)}.${Y(r)}.${Y(o)}`}function tt(e){let t=String(e??""),n=t.split(".");if(n.length!==4||n[0]!==Ie)throw new g("tenant-bound object id required","unbound-object");let r=B(n[1],"tenant"),o=B(n[2],"resource"),s=B(n[3],"object");if(!q.test(r)||!Q.has(o))throw new g("tenant-bound object id is invalid","invalid-object-binding");return Te(s),J({schemaVersion:1,tenantId:r,resource:o,objectId:s,boundId:t})}function nt(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 he(e){let t={...e,decisionId:Ee(e)};return J(t)}function rt({context:e,resource:t,action:n,objectId:r=null,decidedAt:o}={}){let s=nt(o),c={schemaVersion:Ze,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:Ee(String(r))}},p=A=>he({...c,allowed:!1,outcome:"deny",reason:A});if(e==null)return p(N.DENY_MISSING_CONTEXT);if(!M(e))return p(N.DENY_INVALID_CONTEXT);if(!s)return p(N.DENY_INVALID_REQUEST);if(!Q.has(t))return p(N.DENY_UNKNOWN_RESOURCE);if(!Ke.has(n))return p(N.DENY_UNKNOWN_ACTION);if(r!=null){let A;try{A=tt(r)}catch{return p(N.DENY_UNBOUND_OBJECT)}if(A.tenantId!==e.tenantId)return p(N.DENY_TENANT_MISMATCH);if(A.resource!==t)return p(N.DENY_RESOURCE_MISMATCH)}if(n===ye.approve&&!e.actor.roles.some(b=>We.includes(b)))return p(N.DENY_ROLE_PERMISSION);let I=`${t}:${n}`,O=e.actor.roles.some(A=>Ne[A]?.includes(I));return he({...c,allowed:O,outcome:O?"allow":"deny",reason:O?N.ALLOW_ROLE_PERMISSION:N.DENY_ROLE_PERMISSION})}function ve(e){let t=rt(e);if(!t.allowed){let n=new g(`tenant access denied: ${t.reason}`,"access-denied");throw n.decision=t,n}return t}import{createHash as ot,randomUUID as st}from"node:crypto";import{chmodSync as it,closeSync as Z,constants as L,existsSync as ne,fsyncSync as re,lstatSync as ke,mkdirSync as Re,openSync as oe,readFileSync as at,renameSync as ct,unlinkSync as se,writeFileSync as xe}from"node:fs";import{dirname as De,resolve as Ce}from"node:path";function ie(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(ie).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${ie(e[t])}`).join(",")}}`}function T(e){return ot("sha256").update(ie(e)).digest("hex")}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 dt(e,t,n){let r=Ce(e),o=De(r);if(Re(o,{recursive:!0,mode:448}),ne(r)){let c=ke(r);if(!c.isFile()||c.isSymbolicLink())throw n("state path must be a regular non-symlink file","unsafe-file")}let s=`${r}.${st()}.tmp`;try{xe(s,`${JSON.stringify(t)}
2
- `,{encoding:"utf8",mode:384,flag:"wx"});let c=oe(s,L.O_RDONLY);try{re(c)}finally{Z(c)}ct(s,r),it(r,384);let p;try{p=oe(o,L.O_RDONLY),re(p)}finally{p!==void 0&&Z(p)}}catch(c){try{ne(s)&&se(s)}catch{}throw c}}function lt(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 c=0;c<e.events.length;c+=1){let p=e.events[c];if(!p||typeof p!="object"||Array.isArray(p))throw n("event is invalid","integrity-failed");if(p.record&&typeof p.record.recordHash=="string"){let{recordHash:A,...b}=p.record;if(T(b)!==A)throw n("record hash integrity failed; state may be tampered","integrity-failed")}let{eventHash:I,...O}=p;if(p.sequence!==c+1||p.previousEventHash!==r||T(O)!==I)throw n("event hash chain integrity failed; state may be tampered","integrity-failed");r=I}let{stateHash:o,...s}=e;if(T(s)!==o)throw n("state hash integrity failed; state may be tampered","integrity-failed");return e}function G(e,t,n){if(!ne(e)){let s={schemaVersion:t,events:[]};return{...s,stateHash:T(s)}}let r=ke(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 o;try{o=JSON.parse(at(e,"utf8"))}catch{throw n("state JSON is malformed","integrity-failed")}return lt(o,t,n)}function ut(e,t,n){let r=`${e}.lock`,o;try{o=oe(r,L.O_CREAT|L.O_EXCL|L.O_WRONLY,384),xe(o,`${JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})}
3
- `,"utf8"),re(o)}catch(s){if(o!==void 0){Z(o);try{se(r)}catch{}}throw s?.code==="EEXIST"?t("state is locked by another writer","state-locked"):s}try{return n()}finally{try{Z(o)}finally{se(r)}}}function je({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=Ce(e);Re(De(r),{recursive:!0,mode:448});let o=G(r,t,n);function s(){let p={schemaVersion:t,events:o.events};o={...p,stateHash:T(p)},dt(r,o,n)}function c({tenantId:p,recordType:I,recordId:O,operation:A,occurredAt:b,record:_,expectedRecordHash:C=null}){return ut(r,n,()=>{if(o=G(r,t,n),(([...o.events].reverse().find(m=>m.record?.boundId===_?.boundId)??null)?.record?.recordHash??null)!==C)throw n("record changed concurrently; retry from current state","state-conflict");if(_&&typeof _.recordHash=="string"){let{recordHash:m,...l}=_;if(T(l)!==m)throw n("record hash is inconsistent","integrity-failed")}let u={sequence:o.events.length+1,previousEventHash:o.events.at(-1)?.eventHash??null,tenantId:p,recordType:I,recordId:O,operation:A,occurredAt:b,record:_},d=k({...u,eventHash:T(u)});return o={...o,events:[...o.events,d]},s(),d})}return Object.freeze({append:c,events:()=>(o=G(r,t,n),o.events.map(p=>structuredClone(p))),verify:()=>{try{return o=G(r,t,n),{ok:!0,count:o.events.length,stateHash:o.stateHash}}catch(p){return{ok:!1,reason:p?.code||"integrity-failed"}}},path:r})}var ft=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])/]),pt=new Set(["apikey","key","token","accesstoken","secret","password","passwd","auth","authorization","bearer","signertoken","credential","credentials","clientsecret","privatekey","xapikey","accesskey","refreshtoken"]),mt=Object.freeze(["apikey","accesskey","privatekey","clientsecret","accesstoken","refreshtoken","signertoken","credential","password","passwd","authorization","bearer","secret","token"]);function ht(e){return String(e??"").replace(/[^a-z0-9]/gi,"").toLowerCase()}function yt(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=ht(n);if(pt.has(r)||mt.some(o=>r.includes(o)))return!0}return!1}function $e(e){try{let t=decodeURIComponent(e);return t===e?null:t}catch{return null}}var gt=/[a-z][a-z0-9+.-]{1,15}(?::\/\/|%3a%2f%2f)\S+/gi;function wt(e){return e.replace(/[),.;:!?'"\]}]+$/,"")}function St(e){let t=e.match(gt)||[];for(let n of t){let r=wt(n),o=$e(r),s=o?$e(o):null;for(let c of[r,o,s])if(c&&yt(c))return!0}return!1}function $(e){return typeof e!="string"||e.length===0?!1:ft.some(t=>t.test(e))?!0:St(e)}var ze="oracle.context-graph/1",It="oracle.context-graph-state/1",bt=Object.freeze(["onchain","api","document","user","system","derived"]),At=/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/,Nt=/^[a-z0-9][a-z0-9._-]{0,95}$/,Et=/^[a-z][a-z0-9._-]{0,63}$/,Ot=/^[0-9a-f]{64}$/,_t=new Set(bt),Tt=32,vt=16,kt=512,Rt=366*24*60*60*1e3,xt=300*1e3,Dt=["authorization","apikey","accesskey","cookie","credential","password","passphrase","secret","token","privatekey","seed","mnemonic","keystore","signature"],ae=class extends Error{constructor(t,n="invalid-context-graph"){super(`context-graph: ${t}`),this.name="ContextGraphError",this.code=n}};function h(e,t){return new ae(e,t)}function Ve(e,t){if(typeof e!="string")throw h(`${t} must be an ISO timestamp`,"invalid-time");let n=Date.parse(e);if(!Number.isFinite(n)||new Date(n).toISOString()!==e)throw h(`${t} must be an ISO timestamp`,"invalid-time");return e}function E(e,t){let n=String(e??"").trim();if($(n))throw h(`${t} contains secret-shaped material`,"secret-material");if(!At.test(n))throw h(`${t} is invalid`,"invalid-id");return n}function R(e){let t=String(e??"").trim();if($(t))throw h("domain contains secret-shaped material","secret-material");if(!Nt.test(t))throw h("domain is invalid","invalid-domain");return t}function He(e){let t=String(e??"").trim();if($(t))throw h("relation contains secret-shaped material","secret-material");if(!Et.test(t))throw h("relation is invalid","invalid-relation");return t}function Le(e,t){if(typeof e=="string"){if(e.length>kt)throw h(`${t} string is too long`,"attribute-too-large");if($(e))throw h(`${t} contains secret-shaped material`,"secret-material");return e}if(typeof e=="boolean"||e===null||typeof e=="number"&&Number.isFinite(e))return e;throw h(`${t} must be a scalar or scalar array`,"invalid-attribute")}function Pe(e={}){if(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)throw h("attributes must be a plain object","invalid-attributes");let t=Object.keys(e).sort();if(t.length>Tt)throw h("attributes exceed the field limit","attribute-limit");let n={};for(let r of t){if(!/^[A-Za-z][A-Za-z0-9_.-]{0,47}$/.test(r))throw h(`attribute key ${r} is invalid`,"invalid-attribute-key");let o=r.replace(/[^a-z0-9]/gi,"").toLowerCase();if(Dt.some(s=>o.includes(s)))throw h(`attribute key ${r} is forbidden because it may contain a secret`,"secret-material");if(Array.isArray(e[r])){if(e[r].length>vt)throw h(`${r} array is too long`,"attribute-limit");n[r]=e[r].map((s,c)=>Le(s,`${r}[${c}]`))}else n[r]=Le(e[r],r)}return n}function Me(e,t,n){if(!e||typeof e!="object"||Array.isArray(e))throw h("provenance is required","missing-provenance");let r=String(e.sourceType??"").trim();if(!_t.has(r))throw h("provenance sourceType is invalid","invalid-provenance");let o=String(e.source??"").trim();if(!o||o.length>512||/[\u0000-\u001f\u007f]/.test(o)||$(o))throw h("provenance source is invalid","invalid-provenance");let s=String(e.evidenceHash??"").trim().toLowerCase();if(!Ot.test(s))throw h("provenance evidenceHash must be sha256","invalid-provenance");let c=Ve(e.observedAt,"provenance.observedAt");if(Date.parse(c)>Date.parse(t)+xt)throw h("provenance observedAt is too far in the future","future-observation");return{sourceType:r,source:o,observedAt:c,evidenceHash:s,verification:"unverified",assertedBy:E(n.actor.actorId,"assertedBy")}}function Ye(e,t){if(e&&Date.parse(t.observedAt)<Date.parse(e.provenance.observedAt))throw h("provenance observedAt is out of order relative to the existing record","out-of-order-provenance")}function Ue(e,t,n){if(!e||typeof e!="object"||Array.isArray(e))throw h("freshness policy is required","missing-freshness");let r=Number(e.maxAgeMs);if(!Number.isSafeInteger(r)||r<1||r>Rt)throw h("freshness.maxAgeMs is invalid","invalid-freshness");let o=Date.parse(t)+r;if(!Number.isSafeInteger(o))throw h("freshness expiry is invalid","invalid-freshness");let s=new Date(o).toISOString();return{maxAgeMs:r,expiresAt:s,status:Date.parse(n)<o?"fresh":"stale"}}function z(e){return{...e,freshness:{maxAgeMs:e.freshness.maxAgeMs,expiresAt:e.freshness.expiresAt}}}function x(e,t){if(!e)return null;let n=Date.parse(t)<Date.parse(e.freshness.expiresAt)?"fresh":"stale";return k(structuredClone({...e,freshness:{...e.freshness,status:n}}))}function P(e){let t=new Map;for(let n of e)t.set(`${n.tenantId}\0${n.recordType}\0${n.record.domain}\0${n.recordId}`,n.record);return t}function qe({path:e,now:t=()=>new Date().toISOString()}={}){let n=je({path:e,schemaVersion:It,fail:h});function r(){return Ve(t(),"now")}function o(i,u,d=null,m=r()){return d!=null&&F(i,d),ve({context:i,resource:"context",action:u,decidedAt:m})}function s(i,u,d,m){return P(n.events()).get(`${i.tenantId}\0${u}\0${d}\0${m}`)??null}function c({context:i,input:u}={}){H(i);let d=r(),m=R(u?.domain);F(i,m);let l=E(u?.nodeId,"nodeId"),f=s(i,"node",m,l);o(i,f?"update":"create",m,d);let y=Me(u?.provenance,d,i);Ye(f,y);let S=Ue(u?.freshness,y.observedAt,d),w={schemaVersion:ze,recordType:"node",tenantId:i.tenantId,boundId:te(i,"context",`node:${m}:${l}`),domain:m,nodeId:l,kind:E(u?.kind,"kind"),attributes:Pe(u?.attributes),provenance:y,freshness:S,recordedAt:d,revision:f?f.revision+1:1},a={...w,recordHash:T(z(w))};return n.append({tenantId:i.tenantId,recordType:"node",recordId:l,operation:f?"update":"create",occurredAt:d,record:z(a),expectedRecordHash:f?.recordHash??null}),x(z(a),d)}function p({context:i,input:u}={}){H(i);let d=r(),m=R(u?.domain);F(i,m);let l=E(u?.edgeId,"edgeId"),f=E(u?.fromNodeId,"fromNodeId"),y=E(u?.toNodeId,"toNodeId");if(!s(i,"node",m,f)||!s(i,"node",m,y))throw h("edge references a missing node in its domain","missing-node");let S=s(i,"edge",m,l);o(i,S?"update":"create",m,d);let w=He(u?.relation),a=Me(u?.provenance,d,i);Ye(S,a);let D=Ue(u?.freshness,a.observedAt,d),ce={schemaVersion:ze,recordType:"edge",tenantId:i.tenantId,boundId:te(i,"context",`edge:${m}:${l}`),domain:m,edgeId:l,fromNodeId:f,toNodeId:y,relation:w,attributes:Pe(u?.attributes),provenance:a,freshness:D,recordedAt:d,revision:S?S.revision+1:1},de={...ce,recordHash:T(z(ce))};return n.append({tenantId:i.tenantId,recordType:"edge",recordId:l,operation:S?"update":"create",occurredAt:d,record:z(de),expectedRecordHash:S?.recordHash??null}),x(z(de),d)}function I({context:i,domain:u,nodeId:d,includeStale:m=!1}={}){let l=r(),f=R(u);o(i,"read",f,l);let y=x(s(i,"node",f,E(d,"nodeId")),l);return y&&(m||y.freshness.status==="fresh")?y:null}function O({context:i,domain:u,edgeId:d,includeStale:m=!1}={}){let l=r(),f=R(u);o(i,"read",f,l);let y=x(s(i,"edge",f,E(d,"edgeId")),l);return y&&(m||y.freshness.status==="fresh")?y:null}function A({context:i,domain:u,kinds:d=null,includeStale:m=!1,limit:l=100}={}){let f=r(),y=R(u);if(o(i,"read",y,f),!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let S=d==null?null:new Set(d.map(a=>E(a,"kind"))),w=[...P(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="node"&&a.domain===y).filter(a=>!S||S.has(a.kind)).map(a=>x(a,f)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.nodeId.localeCompare(D.nodeId)).slice(0,l);return k({domain:y,count:w.length,records:w})}function b({context:i,domain:u,relations:d=null,includeStale:m=!1,limit:l=100}={}){let f=r(),y=R(u);if(o(i,"read",y,f),!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let S=d==null?null:new Set(d.map(a=>He(a))),w=[...P(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="edge"&&a.domain===y).filter(a=>!S||S.has(a.relation)).map(a=>x(a,f)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.edgeId.localeCompare(D.edgeId)).slice(0,l);return k({domain:y,count:w.length,records:w})}function _({context:i,domain:u,nodeId:d,includeStale:m=!1,limit:l=100}={}){let f=r(),y=R(u);o(i,"read",y,f);let S=E(d,"nodeId");if(!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let w=[...P(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="edge"&&a.domain===y).filter(a=>a.fromNodeId===S||a.toNodeId===S).map(a=>x(a,f)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.edgeId.localeCompare(D.edgeId)).slice(0,l);return k({domain:y,nodeId:S,count:w.length,records:w})}function C({context:i}={}){let u=r();return o(i,"read",null,u),[...new Set([...P(n.events()).values()].filter(d=>d.tenantId===i.tenantId&&ee(i,d.domain)).map(d=>d.domain))].sort()}function j({context:i,domain:u,recordId:d,recordType:m="node",limit:l=100}={}){let f=r(),y=R(u);o(i,"read",y,f);let S=E(d,"recordId");if(!["node","edge"].includes(m))throw h("recordType must be node or edge","invalid-record-type");if(!Number.isSafeInteger(l)||l<1||l>500)throw h("history limit is invalid","invalid-limit");return n.events().filter(w=>w.tenantId===i.tenantId&&w.recordType===m&&w.record.domain===y&&w.recordId===S).slice(-l).map(w=>k({operation:w.operation,occurredAt:w.occurredAt,eventHash:w.eventHash,record:x(w.record,f)}))}return Object.freeze({putNode:c,putEdge:p,getNode:I,getEdge:O,query:A,queryEdges:b,neighbors:_,listDomains:C,history:j,verify:n.verify})}var X=`oracle context <command> [options]
1
+ import{readFileSync as Je}from"node:fs";import{homedir as jt}from"node:os";import{join as Ct}from"node:path";import{createHash as Be}from"node:crypto";var Y=1,V=1,Ge=1,le="local-owner",fe="local-owner",Ze=Object.freeze(["owner","operator","agent","viewer"]),Xe=Object.freeze(["tenant","config","policy","grant","workflow","trade","receipt","audit","telemetry","context","lifecycle"]),ye=Object.freeze({read:"read",create:"create",update:"update",delete:"delete",manage:"manage",prepare:"prepare",cancel:"cancel",export:"export",approve:"approve"}),We=Object.freeze(["owner"]),E=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"}),ge=new Set(Ze),Q=new Set(Xe),Ke=new Set(Object.values(ye)),we=new Set(["user","service","local-owner"]),be=new Set(["verified-session","service-credential","desktop-session","owner-arm-token","local-owner"]),q=/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,127}$/,Se="tob1",Ie=new WeakSet,Ae=new WeakMap,Ee=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"])}),Ht=Object.freeze(Object.fromEntries(Object.entries(Ee).map(([e,t])=>[e,Object.freeze([...t])]))),g=class extends Error{constructor(t,n="invalid-context"){super(t),this.name="TenantContextError",this.code=n}};function W(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype}function J(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))J(t)}return e}function K(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(K).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${K(e[t])}`).join(",")}}`}function Oe(e){return Be("sha256").update(K(e)).digest("hex")}function ue(e,t,n){if(!W(e))throw new g(`${n} must be a plain object`);let r=Object.keys(e).filter(o=>!t.has(o));if(r.length)throw new g(`${n} has unknown fields: ${r.sort().join(", ")}`)}function pe(e,t){let n=String(e??"").trim();if(!q.test(n))throw new g(`${t} is invalid`);return n}function me(e,t="assignedRoles"){if(!Array.isArray(e)||e.length===0)throw new g(`${t} must contain at least one trusted role`,"missing-role-assignment");let n=[...new Set(e.map(o=>String(o??"").trim()))].sort(),r=n.filter(o=>!ge.has(o));if(r.length)throw new g(`${t} contains unknown roles: ${r.join(", ")}`,"unknown-role");return n}function Ne(e,t){return e.length===t.length&&e.every((n,r)=>n===t[r])}function Qe(e){if(!W(e)||e.schemaVersion!==Y||!q.test(e.tenantId||"")||typeof e.localCompatibility!="boolean")return!1;let t=e.actor;if(!W(t)||t.schemaVersion!==V||!q.test(t.actorId||"")||!we.has(t.actorType)||!be.has(t.authSource)||!Array.isArray(t.roles)||t.roles.length===0)return!1;let n=[...new Set(t.roles)].sort();return n.every(r=>ge.has(r))&&Ne(n,t.roles)}function et(e,{assignedTenantId:t,assignedActorId:n,assignedActorType:r,assignedAuthSource:o,assignedRoles:s,assignedContextDomains:c=null,localCompatibility:p=!1}={}){let S=e;if(ue(S,new Set(["schemaVersion","tenantId","actor","localCompatibility"]),"tenant claims"),S.schemaVersion!=null&&S.schemaVersion!==Y)throw new g("unsupported tenant context schema version","unsupported-version");if(![t,n,r,o].every(u=>u!=null))throw new g("trusted tenant and actor identity assignments are required","missing-trusted-identity");let I=S.actor??{};if(ue(I,new Set(["schemaVersion","actorId","actorType","authSource","roles"]),"actor claims"),I.schemaVersion!=null&&I.schemaVersion!==V)throw new g("unsupported actor identity schema version","unsupported-version");let x=pe(t,"tenantId"),j=pe(n,"actorId"),C=String(r).trim(),i=String(o).trim();if(!we.has(C))throw new g("actorType is invalid");if(!be.has(i))throw new g("authSource is invalid");let f=me(s);if(!Array.isArray(c)&&c!=null)throw new g("assignedContextDomains must be an array","invalid-domain-assignment");let d=c==null?f.includes("owner")?["*"]:[]:[...new Set(c.map(u=>String(u??"").trim()))].sort();if(d.some(u=>u!=="*"&&!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(u)))throw new g("assignedContextDomains contains an invalid domain","invalid-domain-assignment");if(I.roles!==void 0){let u;try{u=me(I.roles,"claimed roles")}catch{throw new g("claimed roles do not match the trusted assignment","forged-role")}if(!Ne(u,f))throw new g("claimed roles do not match the trusted assignment","forged-role")}if(S.localCompatibility!==void 0&&S.localCompatibility!==p)throw new g("local compatibility may only be set by the trusted boundary","forged-local-compatibility");if([[S.tenantId,x],[I.actorId,j],[I.actorType,C],[I.authSource,i]].some(([u,y])=>u!==void 0&&String(u).trim()!==y))throw new g("claimed identity does not match the trusted assignment","forged-identity");let l=J({schemaVersion:Y,tenantId:x,actor:{schemaVersion:V,actorId:j,actorType:C,authSource:i,roles:f},localCompatibility:p===!0});return Ie.add(l),Ae.set(l,Object.freeze(d)),l}function ee(e,t){H(e);let n=String(t??"").trim();if(!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(n))return!1;let r=Ae.get(e)||[];return r.includes("*")||r.includes(n)}function F(e,t){if(!ee(e,t))throw new g("context domain access denied","domain-access-denied");return t}function xe({authSource:e="local-owner"}={}){if(!new Set(["local-owner","desktop-session","owner-arm-token"]).has(e))throw new g("local owner authSource is invalid");return et({schemaVersion:Y,tenantId:le,actor:{schemaVersion:V,actorId:fe,actorType:"local-owner",authSource:e}},{assignedTenantId:le,assignedActorId:fe,assignedActorType:"local-owner",assignedAuthSource:e,assignedRoles:["owner"],localCompatibility:!0})}function M(e){return Ie.has(e)&&Qe(e)}function H(e){if(!M(e))throw new g("a resolved tenant context is required","unresolved-context");return e}function U(e){return Buffer.from(e,"utf8").toString("base64url")}function X(e,t){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))throw new g(`${t} binding is invalid`,"invalid-object-binding");let n=Buffer.from(e,"base64url").toString("utf8");if(!n||U(n)!==e)throw new g(`${t} binding is non-canonical`,"invalid-object-binding");return n}function _e(e){let t=String(e??"").trim();if(!t||t.length>256||/[\u0000-\u001f\u007f]/.test(t))throw new g("objectId is invalid","invalid-object-id");return t}function te(e,t,n){H(e);let r=String(t??"").trim();if(!Q.has(r))throw new g("resource is unknown","unknown-resource");let o=_e(n);return`${Se}.${U(e.tenantId)}.${U(r)}.${U(o)}`}function tt(e){let t=String(e??""),n=t.split(".");if(n.length!==4||n[0]!==Se)throw new g("tenant-bound object id required","unbound-object");let r=X(n[1],"tenant"),o=X(n[2],"resource"),s=X(n[3],"object");if(!q.test(r)||!Q.has(o))throw new g("tenant-bound object id is invalid","invalid-object-binding");return _e(s),J({schemaVersion:1,tenantId:r,resource:o,objectId:s,boundId:t})}function nt(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 he(e){let t={...e,decisionId:Oe(e)};return J(t)}function rt({context:e,resource:t,action:n,objectId:r=null,decidedAt:o}={}){let s=nt(o),c={schemaVersion:Ge,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:Oe(String(r))}},p=A=>he({...c,allowed:!1,outcome:"deny",reason:A});if(e==null)return p(E.DENY_MISSING_CONTEXT);if(!M(e))return p(E.DENY_INVALID_CONTEXT);if(!s)return p(E.DENY_INVALID_REQUEST);if(!Q.has(t))return p(E.DENY_UNKNOWN_RESOURCE);if(!Ke.has(n))return p(E.DENY_UNKNOWN_ACTION);if(r!=null){let A;try{A=tt(r)}catch{return p(E.DENY_UNBOUND_OBJECT)}if(A.tenantId!==e.tenantId)return p(E.DENY_TENANT_MISMATCH);if(A.resource!==t)return p(E.DENY_RESOURCE_MISMATCH)}if(n===ye.approve&&!e.actor.roles.some(I=>We.includes(I)))return p(E.DENY_ROLE_PERMISSION);let S=`${t}:${n}`,N=e.actor.roles.some(A=>Ee[A]?.includes(S));return he({...c,allowed:N,outcome:N?"allow":"deny",reason:N?E.ALLOW_ROLE_PERMISSION:E.DENY_ROLE_PERMISSION})}function Te(e){let t=rt(e);if(!t.allowed){let n=new g(`tenant access denied: ${t.reason}`,"access-denied");throw n.decision=t,n}return t}import{createHash as ot,randomUUID as st}from"node:crypto";import{chmodSync as it,closeSync as G,constants as P,existsSync as ne,fsyncSync as re,lstatSync as ve,mkdirSync as ke,openSync as oe,readFileSync as at,renameSync as ct,unlinkSync as se,writeFileSync as Re}from"node:fs";import{dirname as De,resolve as je}from"node:path";function ie(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(ie).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${ie(e[t])}`).join(",")}}`}function _(e){return ot("sha256").update(ie(e)).digest("hex")}function v(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))v(t)}return e}function dt(e,t,n){let r=je(e),o=De(r);if(ke(o,{recursive:!0,mode:448}),ne(r)){let c=ve(r);if(!c.isFile()||c.isSymbolicLink())throw n("state path must be a regular non-symlink file","unsafe-file")}let s=`${r}.${st()}.tmp`;try{Re(s,`${JSON.stringify(t)}
2
+ `,{encoding:"utf8",mode:384,flag:"wx"});let c=oe(s,P.O_RDONLY);try{re(c)}finally{G(c)}ct(s,r),it(r,384);let p;try{p=oe(o,P.O_RDONLY),re(p)}finally{p!==void 0&&G(p)}}catch(c){try{ne(s)&&se(s)}catch{}throw c}}function lt(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 c=0;c<e.events.length;c+=1){let p=e.events[c];if(!p||typeof p!="object"||Array.isArray(p))throw n("event is invalid","integrity-failed");if(p.record&&typeof p.record.recordHash=="string"){let{recordHash:A,...I}=p.record;if(_(I)!==A)throw n("record hash integrity failed; state may be tampered","integrity-failed")}let{eventHash:S,...N}=p;if(p.sequence!==c+1||p.previousEventHash!==r||_(N)!==S)throw n("event hash chain integrity failed; state may be tampered","integrity-failed");r=S}let{stateHash:o,...s}=e;if(_(s)!==o)throw n("state hash integrity failed; state may be tampered","integrity-failed");return e}function B(e,t,n){if(!ne(e)){let s={schemaVersion:t,events:[]};return{...s,stateHash:_(s)}}let r=ve(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 o;try{o=JSON.parse(at(e,"utf8"))}catch{throw n("state JSON is malformed","integrity-failed")}return lt(o,t,n)}function ft(e,t,n){let r=`${e}.lock`,o;try{o=oe(r,P.O_CREAT|P.O_EXCL|P.O_WRONLY,384),Re(o,`${JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})}
3
+ `,"utf8"),re(o)}catch(s){if(o!==void 0){G(o);try{se(r)}catch{}}throw s?.code==="EEXIST"?t("state is locked by another writer","state-locked"):s}try{return n()}finally{try{G(o)}finally{se(r)}}}function Ce({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=je(e);ke(De(r),{recursive:!0,mode:448});let o=B(r,t,n);function s(){let p={schemaVersion:t,events:o.events};o={...p,stateHash:_(p)},dt(r,o,n)}function c({tenantId:p,recordType:S,recordId:N,operation:A,occurredAt:I,record:x,expectedRecordHash:j=null}){return ft(r,n,()=>{if(o=B(r,t,n),(([...o.events].reverse().find(m=>m.record?.boundId===x?.boundId)??null)?.record?.recordHash??null)!==j)throw n("record changed concurrently; retry from current state","state-conflict");if(x&&typeof x.recordHash=="string"){let{recordHash:m,...l}=x;if(_(l)!==m)throw n("record hash is inconsistent","integrity-failed")}let f={sequence:o.events.length+1,previousEventHash:o.events.at(-1)?.eventHash??null,tenantId:p,recordType:S,recordId:N,operation:A,occurredAt:I,record:x},d=v({...f,eventHash:_(f)});return o={...o,events:[...o.events,d]},s(),d})}return Object.freeze({append:c,events:()=>(o=B(r,t,n),o.events.map(p=>structuredClone(p))),verify:()=>{try{return o=B(r,t,n),{ok:!0,count:o.events.length,stateHash:o.stateHash}}catch(p){return{ok:!1,reason:p?.code||"integrity-failed"}}},path:r})}var ut=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])/]),pt=new Set(["apikey","key","token","accesstoken","secret","password","passwd","auth","authorization","bearer","signertoken","credential","credentials","clientsecret","privatekey","xapikey","accesskey","refreshtoken"]),mt=Object.freeze(["apikey","accesskey","privatekey","clientsecret","accesstoken","refreshtoken","signertoken","credential","password","passwd","authorization","bearer","secret","token"]);function ht(e){return String(e??"").replace(/[^a-z0-9]/gi,"").toLowerCase()}function yt(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=ht(n);if(pt.has(r)||mt.some(o=>r.includes(o)))return!0}return!1}function ze(e){try{let t=decodeURIComponent(e);return t===e?null:t}catch{return null}}var gt=/[a-z][a-z0-9+.-]{1,15}(?::\/\/|%3a%2f%2f)\S+/gi;function wt(e){return e.replace(/[),.;:!?'"\]}]+$/,"")}function bt(e){let t=e.match(gt)||[];for(let n of t){let r=wt(n),o=ze(r),s=o?ze(o):null;for(let c of[r,o,s])if(c&&yt(c))return!0}return!1}var Vt=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 z(e){return typeof e!="string"||e.length===0?!1:ut.some(t=>t.test(e))?!0:bt(e)}var $e="oracle.context-graph/1",St="oracle.context-graph-state/1",It=Object.freeze(["onchain","api","document","user","system","derived"]),At=/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/,Et=/^[a-z0-9][a-z0-9._-]{0,95}$/,Ot=/^[a-z][a-z0-9._-]{0,63}$/,Nt=/^[0-9a-f]{64}$/,xt=new Set(It),_t=32,Tt=16,vt=512,kt=366*24*60*60*1e3,Rt=300*1e3,Dt=["authorization","apikey","accesskey","cookie","credential","password","passphrase","secret","token","privatekey","seed","mnemonic","keystore","signature"],ae=class extends Error{constructor(t,n="invalid-context-graph"){super(`context-graph: ${t}`),this.name="ContextGraphError",this.code=n}};function h(e,t){return new ae(e,t)}function Ve(e,t){if(typeof e!="string")throw h(`${t} must be an ISO timestamp`,"invalid-time");let n=Date.parse(e);if(!Number.isFinite(n)||new Date(n).toISOString()!==e)throw h(`${t} must be an ISO timestamp`,"invalid-time");return e}function O(e,t){let n=String(e??"").trim();if(z(n))throw h(`${t} contains secret-shaped material`,"secret-material");if(!At.test(n))throw h(`${t} is invalid`,"invalid-id");return n}function k(e){let t=String(e??"").trim();if(z(t))throw h("domain contains secret-shaped material","secret-material");if(!Et.test(t))throw h("domain is invalid","invalid-domain");return t}function He(e){let t=String(e??"").trim();if(z(t))throw h("relation contains secret-shaped material","secret-material");if(!Ot.test(t))throw h("relation is invalid","invalid-relation");return t}function Pe(e,t){if(typeof e=="string"){if(e.length>vt)throw h(`${t} string is too long`,"attribute-too-large");if(z(e))throw h(`${t} contains secret-shaped material`,"secret-material");return e}if(typeof e=="boolean"||e===null||typeof e=="number"&&Number.isFinite(e))return e;throw h(`${t} must be a scalar or scalar array`,"invalid-attribute")}function Le(e={}){if(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)throw h("attributes must be a plain object","invalid-attributes");let t=Object.keys(e).sort();if(t.length>_t)throw h("attributes exceed the field limit","attribute-limit");let n={};for(let r of t){if(!/^[A-Za-z][A-Za-z0-9_.-]{0,47}$/.test(r))throw h(`attribute key ${r} is invalid`,"invalid-attribute-key");let o=r.replace(/[^a-z0-9]/gi,"").toLowerCase();if(Dt.some(s=>o.includes(s)))throw h(`attribute key ${r} is forbidden because it may contain a secret`,"secret-material");if(Array.isArray(e[r])){if(e[r].length>Tt)throw h(`${r} array is too long`,"attribute-limit");n[r]=e[r].map((s,c)=>Pe(s,`${r}[${c}]`))}else n[r]=Pe(e[r],r)}return n}function Me(e,t,n){if(!e||typeof e!="object"||Array.isArray(e))throw h("provenance is required","missing-provenance");let r=String(e.sourceType??"").trim();if(!xt.has(r))throw h("provenance sourceType is invalid","invalid-provenance");let o=String(e.source??"").trim();if(!o||o.length>512||/[\u0000-\u001f\u007f]/.test(o)||z(o))throw h("provenance source is invalid","invalid-provenance");let s=String(e.evidenceHash??"").trim().toLowerCase();if(!Nt.test(s))throw h("provenance evidenceHash must be sha256","invalid-provenance");let c=Ve(e.observedAt,"provenance.observedAt");if(Date.parse(c)>Date.parse(t)+Rt)throw h("provenance observedAt is too far in the future","future-observation");return{sourceType:r,source:o,observedAt:c,evidenceHash:s,verification:"unverified",assertedBy:O(n.actor.actorId,"assertedBy")}}function Ue(e,t){if(e&&Date.parse(t.observedAt)<Date.parse(e.provenance.observedAt))throw h("provenance observedAt is out of order relative to the existing record","out-of-order-provenance")}function Ye(e,t,n){if(!e||typeof e!="object"||Array.isArray(e))throw h("freshness policy is required","missing-freshness");let r=Number(e.maxAgeMs);if(!Number.isSafeInteger(r)||r<1||r>kt)throw h("freshness.maxAgeMs is invalid","invalid-freshness");let o=Date.parse(t)+r;if(!Number.isSafeInteger(o))throw h("freshness expiry is invalid","invalid-freshness");let s=new Date(o).toISOString();return{maxAgeMs:r,expiresAt:s,status:Date.parse(n)<o?"fresh":"stale"}}function $(e){return{...e,freshness:{maxAgeMs:e.freshness.maxAgeMs,expiresAt:e.freshness.expiresAt}}}function R(e,t){if(!e)return null;let n=Date.parse(t)<Date.parse(e.freshness.expiresAt)?"fresh":"stale";return v(structuredClone({...e,freshness:{...e.freshness,status:n}}))}function L(e){let t=new Map;for(let n of e)t.set(`${n.tenantId}\0${n.recordType}\0${n.record.domain}\0${n.recordId}`,n.record);return t}function qe({path:e,now:t=()=>new Date().toISOString()}={}){let n=Ce({path:e,schemaVersion:St,fail:h});function r(){return Ve(t(),"now")}function o(i,f,d=null,m=r()){return d!=null&&F(i,d),Te({context:i,resource:"context",action:f,decidedAt:m})}function s(i,f,d,m){return L(n.events()).get(`${i.tenantId}\0${f}\0${d}\0${m}`)??null}function c({context:i,input:f}={}){H(i);let d=r(),m=k(f?.domain);F(i,m);let l=O(f?.nodeId,"nodeId"),u=s(i,"node",m,l);o(i,u?"update":"create",m,d);let y=Me(f?.provenance,d,i);Ue(u,y);let b=Ye(f?.freshness,y.observedAt,d),w={schemaVersion:$e,recordType:"node",tenantId:i.tenantId,boundId:te(i,"context",`node:${m}:${l}`),domain:m,nodeId:l,kind:O(f?.kind,"kind"),attributes:Le(f?.attributes),provenance:y,freshness:b,recordedAt:d,revision:u?u.revision+1:1},a={...w,recordHash:_($(w))};return n.append({tenantId:i.tenantId,recordType:"node",recordId:l,operation:u?"update":"create",occurredAt:d,record:$(a),expectedRecordHash:u?.recordHash??null}),R($(a),d)}function p({context:i,input:f}={}){H(i);let d=r(),m=k(f?.domain);F(i,m);let l=O(f?.edgeId,"edgeId"),u=O(f?.fromNodeId,"fromNodeId"),y=O(f?.toNodeId,"toNodeId");if(!s(i,"node",m,u)||!s(i,"node",m,y))throw h("edge references a missing node in its domain","missing-node");let b=s(i,"edge",m,l);o(i,b?"update":"create",m,d);let w=He(f?.relation),a=Me(f?.provenance,d,i);Ue(b,a);let D=Ye(f?.freshness,a.observedAt,d),ce={schemaVersion:$e,recordType:"edge",tenantId:i.tenantId,boundId:te(i,"context",`edge:${m}:${l}`),domain:m,edgeId:l,fromNodeId:u,toNodeId:y,relation:w,attributes:Le(f?.attributes),provenance:a,freshness:D,recordedAt:d,revision:b?b.revision+1:1},de={...ce,recordHash:_($(ce))};return n.append({tenantId:i.tenantId,recordType:"edge",recordId:l,operation:b?"update":"create",occurredAt:d,record:$(de),expectedRecordHash:b?.recordHash??null}),R($(de),d)}function S({context:i,domain:f,nodeId:d,includeStale:m=!1}={}){let l=r(),u=k(f);o(i,"read",u,l);let y=R(s(i,"node",u,O(d,"nodeId")),l);return y&&(m||y.freshness.status==="fresh")?y:null}function N({context:i,domain:f,edgeId:d,includeStale:m=!1}={}){let l=r(),u=k(f);o(i,"read",u,l);let y=R(s(i,"edge",u,O(d,"edgeId")),l);return y&&(m||y.freshness.status==="fresh")?y:null}function A({context:i,domain:f,kinds:d=null,includeStale:m=!1,limit:l=100}={}){let u=r(),y=k(f);if(o(i,"read",y,u),!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let b=d==null?null:new Set(d.map(a=>O(a,"kind"))),w=[...L(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="node"&&a.domain===y).filter(a=>!b||b.has(a.kind)).map(a=>R(a,u)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.nodeId.localeCompare(D.nodeId)).slice(0,l);return v({domain:y,count:w.length,records:w})}function I({context:i,domain:f,relations:d=null,includeStale:m=!1,limit:l=100}={}){let u=r(),y=k(f);if(o(i,"read",y,u),!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let b=d==null?null:new Set(d.map(a=>He(a))),w=[...L(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="edge"&&a.domain===y).filter(a=>!b||b.has(a.relation)).map(a=>R(a,u)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.edgeId.localeCompare(D.edgeId)).slice(0,l);return v({domain:y,count:w.length,records:w})}function x({context:i,domain:f,nodeId:d,includeStale:m=!1,limit:l=100}={}){let u=r(),y=k(f);o(i,"read",y,u);let b=O(d,"nodeId");if(!Number.isSafeInteger(l)||l<1||l>500)throw h("query limit is invalid","invalid-limit");let w=[...L(n.events()).values()].filter(a=>a.tenantId===i.tenantId&&a.recordType==="edge"&&a.domain===y).filter(a=>a.fromNodeId===b||a.toNodeId===b).map(a=>R(a,u)).filter(a=>m||a.freshness.status==="fresh").sort((a,D)=>a.edgeId.localeCompare(D.edgeId)).slice(0,l);return v({domain:y,nodeId:b,count:w.length,records:w})}function j({context:i}={}){let f=r();return o(i,"read",null,f),[...new Set([...L(n.events()).values()].filter(d=>d.tenantId===i.tenantId&&ee(i,d.domain)).map(d=>d.domain))].sort()}function C({context:i,domain:f,recordId:d,recordType:m="node",limit:l=100}={}){let u=r(),y=k(f);o(i,"read",y,u);let b=O(d,"recordId");if(!["node","edge"].includes(m))throw h("recordType must be node or edge","invalid-record-type");if(!Number.isSafeInteger(l)||l<1||l>500)throw h("history limit is invalid","invalid-limit");return n.events().filter(w=>w.tenantId===i.tenantId&&w.recordType===m&&w.record.domain===y&&w.recordId===b).slice(-l).map(w=>v({operation:w.operation,occurredAt:w.occurredAt,eventHash:w.eventHash,record:R(w.record,u)}))}return Object.freeze({putNode:c,putEdge:p,getNode:S,getEdge:N,query:A,queryEdges:I,neighbors:x,listDomains:j,history:C,verify:n.verify})}var Z=`oracle context <command> [options]
4
4
  put-node <input.json|-> create or version a node
5
5
  put-edge <input.json|-> create or version an edge
6
6
  get --domain D --id ID read one fresh node
@@ -11,6 +11,6 @@ import{readFileSync as Je}from"node:fs";import{homedir as Ct}from"node:os";impor
11
11
  domains list tenant domains
12
12
  history --domain D --id ID [--type node|edge] [--limit N] read bounded immutable record history
13
13
  verify verify the durable hash chain
14
- Options: --store PATH --include-stale`;function $t(e){let t=[],n={},r=new Set(["store","domain","id","kind","relation","limit","type"]);for(let o=0;o<e.length;o+=1){let s=e[o];if(!s.startsWith("--")){t.push(s);continue}let c=s.slice(2);if(c==="include-stale"){n[c]=!0;continue}if(!r.has(c)||e[o+1]==null)throw new TypeError(X);n[c]=e[++o]}return{positionals:t,options:n}}function Fe(e){let t=e==="-"?Je(0,"utf8"):Je(e,"utf8");return JSON.parse(t)}function v(e){process.stdout.write(`${JSON.stringify(e,null,2)}
15
- `)}var Qt={name:"context",summary:"manage the tenant-scoped provenance and freshness context graph",group:"system",usage:X,async run(e){let{positionals:t,options:n}=$t(e.argv??[]),r=t[0];if(!r||["help","--help","-h"].includes(r))return process.stdout.write(`${X}
16
- `),0;let o=qe({path:n.store||jt(Ct(),".config","oracle","context-graph.json")}),s=_e(),c=n["include-stale"]===!0;if(r==="put-node")v(o.putNode({context:s,input:Fe(t[1])}));else if(r==="put-edge")v(o.putEdge({context:s,input:Fe(t[1])}));else if(r==="get")v(o.getNode({context:s,domain:n.domain,nodeId:n.id,includeStale:c}));else if(r==="query")v(o.query({context:s,domain:n.domain,kinds:n.kind?[n.kind]:null,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="get-edge")v(o.getEdge({context:s,domain:n.domain,edgeId:n.id,includeStale:c}));else if(r==="query-edges")v(o.queryEdges({context:s,domain:n.domain,relations:n.relation?[n.relation]:null,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="neighbors")v(o.neighbors({context:s,domain:n.domain,nodeId:n.id,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="domains")v(o.listDomains({context:s}));else if(r==="history")v(o.history({context:s,domain:n.domain,recordId:n.id,recordType:n.type||"node",limit:n.limit?Number(n.limit):100}));else if(r==="verify")v(o.verify());else throw new TypeError(X);return 0}};export{Qt as default};
14
+ Options: --store PATH --include-stale`;function zt(e){let t=[],n={},r=new Set(["store","domain","id","kind","relation","limit","type"]);for(let o=0;o<e.length;o+=1){let s=e[o];if(!s.startsWith("--")){t.push(s);continue}let c=s.slice(2);if(c==="include-stale"){n[c]=!0;continue}if(!r.has(c)||e[o+1]==null)throw new TypeError(Z);n[c]=e[++o]}return{positionals:t,options:n}}function Fe(e){let t=e==="-"?Je(0,"utf8"):Je(e,"utf8");return JSON.parse(t)}function T(e){process.stdout.write(`${JSON.stringify(e,null,2)}
15
+ `)}var en={name:"context",summary:"manage the tenant-scoped provenance and freshness context graph",group:"system",usage:Z,async run(e){let{positionals:t,options:n}=zt(e.argv??[]),r=t[0];if(!r||["help","--help","-h"].includes(r))return process.stdout.write(`${Z}
16
+ `),0;let o=qe({path:n.store||Ct(jt(),".config","oracle","context-graph.json")}),s=xe(),c=n["include-stale"]===!0;if(r==="put-node")T(o.putNode({context:s,input:Fe(t[1])}));else if(r==="put-edge")T(o.putEdge({context:s,input:Fe(t[1])}));else if(r==="get")T(o.getNode({context:s,domain:n.domain,nodeId:n.id,includeStale:c}));else if(r==="query")T(o.query({context:s,domain:n.domain,kinds:n.kind?[n.kind]:null,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="get-edge")T(o.getEdge({context:s,domain:n.domain,edgeId:n.id,includeStale:c}));else if(r==="query-edges")T(o.queryEdges({context:s,domain:n.domain,relations:n.relation?[n.relation]:null,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="neighbors")T(o.neighbors({context:s,domain:n.domain,nodeId:n.id,includeStale:c,limit:n.limit?Number(n.limit):100}));else if(r==="domains")T(o.listDomains({context:s}));else if(r==="history")T(o.history({context:s,domain:n.domain,recordId:n.id,recordType:n.type||"node",limit:n.limit?Number(n.limit):100}));else if(r==="verify")T(o.verify());else throw new TypeError(Z);return 0}};export{en as default};