ofauth-shared-core 0.2.0-alpha.1 → 0.2.0-alpha.3
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/dist/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function Oe(i){return!!(i.tenantId||i.branchId||i.attributes&&Object.keys(i.attributes).length>0)}function T(i,e){let t={basic:1,elevated:2};return t[i]>=t[e]}function De(i){return["LOGIN_SUCCESS","LOGIN_FAILED","LOCKOUT_TRIGGERED","SESSION_REVOKED","CONTEXT_SWITCHED","STEP_UP_CHALLENGED","STEP_UP_PASSED","STEP_UP_FAILED"].includes(i)}function z(i,e){if(e)return i.find(t=>t.assignmentId===e)}function ye(i,e,t){var r,n;return(n=(r=z(i,t))!=null?r:z(i,e))!=null?n:i[0]}function Se(i,e){var t;if(e.requiredTenantId&&i.tenantId!==e.requiredTenantId||e.requiredBranchId&&i.branchId!==e.requiredBranchId)return!1;if(e.requiredScopeAttributes){let r=(t=i.attributes)!=null?t:{};for(let[n,s]of Object.entries(e.requiredScopeAttributes))if(r[n]!==s)return!1}return!0}function O(i){var e;if(i&&typeof i=="object"&&i.error&&typeof i.error.code=="string"){let t=new Error(i.error.message||i.error.code);throw t.code=i.error.code,t}return(e=i==null?void 0:i.data)!=null?e:i}async function H(i,e){var o,d,c;let t=O(await i.sessionService.getActiveSession(e.sessionId));if(!t)return null;let r=O(await i.contextService.listAssignments(e.identityId)),n=O(await i.contextService.getActiveContext(e.sessionId)),s=ye(r,n==null?void 0:n.assignmentId,e.preferredAssignmentId);return{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,assignments:r,activeContextAssignmentId:s==null?void 0:s.assignmentId,activeAssignment:s,scopeRef:(c=(d=(o=s==null?void 0:s.scopeRef)!=null?o:n==null?void 0:n.scopeRef)!=null?d:t.activeScopeRef)!=null?c:{},roleRef:s==null?void 0:s.roleRef,assuranceLevel:t.assuranceLevel}}async function ke(i,e){let t=O(await i.identityService.login(e.principal,e.secret,e.scopeRef)),r=await H(i,{sessionId:t.sessionId,identityId:t.identity.identityId,principal:t.identity.principal});if(!r)throw new Error("session is not active after login");return r}async function Ne(i,e){return H(i,e)}async function qe(i,e){let t=await H(i,{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,preferredAssignmentId:e.targetAssignmentId});if(!t)throw new Error("session is not active while switching context");if(t.activeContextAssignmentId!==e.targetAssignmentId)throw new Error("requested assignment is not available for the active identity");return t}function He(i,e={}){var r,n;if(!i)return{allowed:!1,reasonCode:"NO_SESSION"};let t=(r=e.minimumAssuranceLevel)!=null?r:"basic";return T(i.assuranceLevel,t)?(n=e.requiredRoleRefs)!=null&&n.length&&!(!!i.roleRef&&e.requiredRoleRefs.includes(i.roleRef))?{allowed:!1,reasonCode:"ROLE_FORBIDDEN"}:Se(i.scopeRef,e)?{allowed:!0}:{allowed:!1,reasonCode:"SCOPE_FORBIDDEN"}:{allowed:!1,reasonCode:"ASSURANCE_TOO_LOW"}}var P=class{canLoginOffline(e){let t=new Date(e.nowIso).getTime(),r=new Date(e.envelope.expiresAt).getTime();return!Number.isFinite(t)||!Number.isFinite(r)?!1:t<=r}};var L=class extends Error{constructor(t,r,n=!1){super(r);this.code=t;this.retryable=n;this.name="OfauthDomainError"}},D=class extends Error{constructor(t){super(t);this.code=t;this.name="AuthRejectionError"}};function A(i,e){return new L(i,e,!1)}function Fe(i){return new L("AUTH_NOT_IMPLEMENTED",i,!1)}var Ae=new Set(["AUTH_UNAUTHORIZED","AUTH_INVALID_CREDENTIAL","AUTH_LOCKED","AUTH_DISABLED"]);function he(i){var e;return{principal:i.principal,accessToken:i.accessToken,refreshToken:i.refreshToken,assuranceLevel:i.assuranceLevel,issuedAt:i.issuedAt,expiresAt:i.expiresAt,activeRoleRef:i.activeRoleRef,activeContext:(e=i.activeContext)!=null?e:null}}function Ke(i){var n,s,o;let e=(n=i.now)!=null?n:(()=>new Date().toISOString()),t=(s=i.isOnline)!=null?s:(()=>!0),r=(o=i.offlinePolicy)!=null?o:new P;return{async login(d){var I,R;let c=String(d.principal||"").trim();if(!c)return{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"};if(t())try{let p=await i.authority.login(d),w=he({principal:c,accessToken:p.accessToken,refreshToken:p.refreshToken,assuranceLevel:p.session.assuranceLevel,issuedAt:p.session.issuedAt,expiresAt:p.session.expiresAt,activeRoleRef:p.activeRoleRef,activeContext:(I=p.activeContext)!=null?I:null}),x={principal:c,identityId:p.session.identityId,roleRef:(R=p.activeRoleRef)!=null?R:null,lastOnlineAuthAt:e()};return await i.cache.setCachedIdentity(x),await i.cache.setSessionEnvelope(c,w),{status:"authenticated",mode:"online",session:w}}catch(p){return p instanceof D?{status:"rejected",reasonCode:p.code}:p instanceof Error&&Ae.has(p.message)?{status:"rejected",reasonCode:p.message}:{status:"rejected",reasonCode:"AUTH_AUTHORITY_UNAVAILABLE"}}let l=await i.cache.getCachedIdentity(c),m=await i.cache.getSessionEnvelope(c);return!l||!m?{status:"rejected",reasonCode:"OFFLINE_SESSION_NOT_AVAILABLE"}:r.canLoginOffline({nowIso:e(),envelope:m})?await i.verifyOfflineSecret({principal:c,secret:d.secret})?{status:"authenticated",mode:"offline",session:m}:{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"}:{status:"rejected",reasonCode:"OFFLINE_SESSION_EXPIRED"}},async logout(d){let c=await i.cache.getSessionEnvelope(d);if(c)try{await i.authority.logout({accessToken:c.accessToken,refreshToken:c.refreshToken})}catch{}}}}function S(i){return{error:{code:"AUTH_NOT_IMPLEMENTED",message:i,retryable:!1}}}function Qe(){return{identityService:{async verifyCredential(){return S("identityService.verifyCredential not implemented yet")},async login(i,e){return S("identityService.login not implemented yet")},async logout(){return S("identityService.logout not implemented yet")}},sessionService:{async createSession(){return S("sessionService.createSession not implemented yet")},async refreshSession(){return S("sessionService.refreshSession not implemented yet")},async revokeSession(){return S("sessionService.revokeSession not implemented yet")},async getActiveSession(){return S("sessionService.getActiveSession not implemented yet")}},contextService:{async listAssignments(){return S("contextService.listAssignments not implemented yet")},async getActiveContext(){return S("contextService.getActiveContext not implemented yet")},async switchContext(){return S("contextService.switchContext not implemented yet")}},authPolicyService:{async getPolicySnapshot(){return S("authPolicyService.getPolicySnapshot not implemented yet")},async getStepUpRequirement(){return S("authPolicyService.getStepUpRequirement not implemented yet")},async evaluateStepUp(){return S("authPolicyService.evaluateStepUp not implemented yet")},async enforceStepUp(){return S("authPolicyService.enforceStepUp not implemented yet")},async markStepUpPassed(){return S("authPolicyService.markStepUpPassed not implemented yet")}},authAuditService:{async appendEvent(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.appendEvent not implemented yet",retryable:!1}},async queryEvents(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.queryEvents not implemented yet",retryable:!1}},async listPendingReplay(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.listPendingReplay not implemented yet",retryable:!1}},async markReplayed(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.markReplayed not implemented yet",retryable:!1}}}}}function f(i,e){return{data:i,meta:{request_id:e!=null?e:null,timestamp:new Date().toISOString()}}}function M(i,e,t={}){var r;return{error:{code:i,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:(r=t.requestId)!=null?r:null,timestamp:new Date().toISOString()}}}function y(i,e="AUTH_NOT_IMPLEMENTED",t="Unhandled auth error."){var r;if(i&&typeof i=="object"){let n=i;return M((r=n.code)!=null?r:e,n.message||t,{retryable:n.retryable})}return i instanceof Error?M(e,i.message||t):M(e,t)}function J(i){return{async verifyCredential(e){try{return f(await i.verifyCredential(e))}catch(t){return y(t)}},async login(e,t,r){try{let n=await i.login({principal:e,secret:t,verifyMethod:"password"});return f(n)}catch(n){return y(n)}},async logout(e){try{return await i.logout(e),f({sessionId:e,revoked:!0})}catch(t){return y(t)}}}}function Z(i){return{async createSession(e){try{return f(await i.createSession(e))}catch(t){return y(t)}},async refreshSession(e){try{return f(await i.refreshSession(e))}catch(t){return y(t)}},async revokeSession(e){try{return await i.revokeSession(e),f({sessionId:e.sessionId,revoked:!0})}catch(t){return y(t)}},async getActiveSession(e){try{return f(await i.getActiveSession(e))}catch(t){return y(t)}}}}function ee(i){return{async listAssignments(e){try{return f(await i.listAssignments(e))}catch(t){return y(t)}},async getActiveContext(e){try{return f(await i.getActiveContext(e))}catch(t){return y(t)}},async switchContext(e){try{return f(await i.switchContext(e))}catch(t){return y(t)}}}}function te(i){return{async getPolicySnapshot(){try{return f(await i.getPolicySnapshot())}catch(e){return y(e)}},async getStepUpRequirement(e){try{return f(await i.getStepUpRequirement(e))}catch(t){return y(t)}},async evaluateStepUp(e,t){try{return f(await i.evaluateStepUp(e,t))}catch(r){return y(r)}},async enforceStepUp(e,t){try{return await i.enforceStepUp(e,t),f({sessionId:e,actionRef:t,enforced:!0})}catch(r){return y(r)}},async markStepUpPassed(e,t){try{return f(await i.markStepUpPassed(e,t))}catch(r){return y(r)}}}}var a={identities:"ofauth_identities",assignments:"ofauth_assignments",sessions:"ofauth_sessions",policyProfiles:"ofauth_policy_profiles",policyStepups:"ofauth_policy_stepups",auditEvents:"ofauth_audit_events"},ve=[{name:a.identities,columns:[{name:"id",type:"string"},{name:"principal",type:"string",isIndexed:!0},{name:"secretHash",type:"string"},{name:"verifyMethod",type:"string",enum:["pin","password","custom"]},{name:"status",type:"string",enum:["active","disabled","locked"],isIndexed:!0},{name:"failedAttempts",type:"number"},{name:"lockoutUntil",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.assignments,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"roleRef",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.sessions,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"activeAssignmentId",type:"string",isOptional:!0,isIndexed:!0},{name:"assuranceLevel",type:"string",enum:["basic","elevated"],isIndexed:!0},{name:"issuedAt",type:"string"},{name:"expiresAt",type:"string",isIndexed:!0},{name:"revokedAt",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyProfiles,columns:[{name:"id",type:"string"},{name:"profileId",type:"string",isIndexed:!0},{name:"defaultAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"lockoutPolicyRef",type:"string"},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyStepups,columns:[{name:"id",type:"string"},{name:"actionRef",type:"string",isIndexed:!0},{name:"requiredAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"reauthWindowSeconds",type:"number",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.auditEvents,columns:[{name:"id",type:"string"},{name:"eventType",type:"string",isIndexed:!0},{name:"identityId",type:"string",isOptional:!0,isIndexed:!0},{name:"sessionId",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"result",type:"string",enum:["success","failed"],isIndexed:!0},{name:"reasonCode",type:"string",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"syncStatus",type:"string",enum:["pending","replayed"],isIndexed:!0},{name:"replayedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]}],ge={version:2,tables:ve};function ie(){return ge.tables}import{makeIdFactory as Ie,nowIso as Re}from"ofcore";var re=5,ne=900,V=480*60;function u(){return Re()}function b(i,e){return new Date(new Date(i).getTime()+e*1e3).toISOString()}function E(i){return new Date(i).getTime()<=Date.now()}function h(i){return Ie(i)}function se(i){return{identityId:i.id,principal:i.principal,status:i.status}}function F(i){return{assignmentId:i.id,identityId:i.identityId,roleRef:i.roleRef,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}}}function C(i,e,t){return{sessionId:i.id,identityId:i.identityId,activeScopeRef:e?{...e.tenantId?{tenantId:e.tenantId}:{},...e.branchId?{branchId:e.branchId}:{},...e.scopeAttributes?{attributes:e.scopeAttributes}:{}}:void 0,grantedAssignments:t!==void 0?t.map(F):void 0,assuranceLevel:i.assuranceLevel,issuedAt:i.issuedAt,expiresAt:i.expiresAt}}async function oe(i,e,t){return i?i.verifyPin(e,t):e===t}async function ae(i,e){var t,r,n,s,o,d;i.emitActivity&&await i.emitActivity({activityId:e.eventId,activityType:`ofauth.${e.eventType.toLowerCase()}`,occurredAt:e.timestamp,scopeRef:{domain:"ofauth",...(t=e.scopeRef)!=null&&t.tenantId?{tenantId:e.scopeRef.tenantId}:{},...(r=e.scopeRef)!=null&&r.branchId?{branchId:e.scopeRef.branchId}:{}},actor:e.identityId?{userId:e.identityId}:void 0,payload:{eventType:e.eventType,result:e.result,reasonCode:(n=e.reasonCode)!=null?n:null,sessionId:(s=e.sessionId)!=null?s:null,scopeAttributes:(d=(o=e.scopeRef)==null?void 0:o.attributes)!=null?d:null}})}async function v(i,e){if(!e)return null;let t=await i.get(a.assignments,e);return!t||t.deleted?null:t}function de(){return[{profileId:"cashier_fast",defaultAssuranceLevel:"basic",lockoutPolicyRef:"default"},{profileId:"supervisor_strict",defaultAssuranceLevel:"elevated",lockoutPolicyRef:"strict"},{profileId:"member_self_service",defaultAssuranceLevel:"basic",lockoutPolicyRef:"member"}]}var _=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-audit")}async appendEvent(e){var r,n,s,o,d,c,l,m,g,I,R;let t={id:e.eventId||this.newId(),eventType:e.eventType,identityId:(r=e.identityId)!=null?r:null,sessionId:(n=e.sessionId)!=null?n:null,tenantId:(o=(s=e.scopeRef)==null?void 0:s.tenantId)!=null?o:null,branchId:(c=(d=e.scopeRef)==null?void 0:d.branchId)!=null?c:null,scopeAttributes:(m=(l=e.scopeRef)==null?void 0:l.attributes)!=null?m:null,result:e.result,reasonCode:(g=e.reasonCode)!=null?g:null,timestamp:e.timestamp,syncStatus:(I=e.syncStatus)!=null?I:"pending",replayedAt:(R=e.replayedAt)!=null?R:null,version:1,lastModified:u(),deleted:!1};await this.db.create(a.auditEvents,t),await ae(this.options,e)}async queryEvents(e){return(await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"desc"}]})).filter(r=>e.identityId?r.identityId===e.identityId:!0).filter(r=>e.sessionId?r.sessionId===e.sessionId:!0).filter(r=>{var n;return(n=e.eventTypes)!=null&&n.length?e.eventTypes.includes(r.eventType):!0}).filter(r=>e.fromTimestamp?r.timestamp>=e.fromTimestamp:!0).filter(r=>e.toTimestamp?r.timestamp<=e.toTimestamp:!0).map(r=>{var n,s,o,d,c;return{eventId:r.id,eventType:r.eventType,identityId:(n=r.identityId)!=null?n:void 0,sessionId:(s=r.sessionId)!=null?s:void 0,scopeRef:r.tenantId||r.branchId||r.scopeAttributes?{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}:void 0,result:r.result,reasonCode:(o=r.reasonCode)!=null?o:void 0,timestamp:r.timestamp,syncStatus:(d=r.syncStatus)!=null?d:"pending",replayedAt:(c=r.replayedAt)!=null?c:void 0}})}async listPendingReplay(e={}){var r;let t=await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"asc"}]});return t.filter(n=>n.syncStatus!=="replayed").slice(0,(r=e.limit)!=null?r:t.length).map(n=>{var s,o,d,c,l;return{eventId:n.id,eventType:n.eventType,identityId:(s=n.identityId)!=null?s:void 0,sessionId:(o=n.sessionId)!=null?o:void 0,scopeRef:n.tenantId||n.branchId||n.scopeAttributes?{...n.tenantId?{tenantId:n.tenantId}:{},...n.branchId?{branchId:n.branchId}:{},...n.scopeAttributes?{attributes:n.scopeAttributes}:{}}:void 0,result:n.result,reasonCode:(d=n.reasonCode)!=null?d:void 0,timestamp:n.timestamp,syncStatus:(c=n.syncStatus)!=null?c:"pending",replayedAt:(l=n.replayedAt)!=null?l:void 0}})}async markReplayed(e,t=u()){let r=0;for(let n of e){let s=await this.db.get(a.auditEvents,n);!s||s.deleted||s.syncStatus==="replayed"||(await this.db.update(a.auditEvents,n,{syncStatus:"replayed",replayedAt:t,version:s.version+1,lastModified:u()}),r+=1)}return r}};var U=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async getActiveSessionOrThrow(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||E(t.expiresAt))throw A("AUTH_SESSION_NOT_FOUND","Session not found");return t}async getPolicySnapshot(){let e=await this.db.query(a.policyProfiles,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),t=await this.db.query(a.policyStepups,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]});return{profiles:e.length>0?e.map(r=>({profileId:r.profileId,defaultAssuranceLevel:r.defaultAssuranceLevel,lockoutPolicyRef:r.lockoutPolicyRef})):de(),stepUpRequirements:t.map(r=>{var n;return{actionRef:r.actionRef,requiredAssuranceLevel:r.requiredAssuranceLevel,reauthWindowSeconds:(n=r.reauthWindowSeconds)!=null?n:void 0}}),version:"1",updatedAt:u()}}async getStepUpRequirement(e){var r;let t=await this.db.query(a.policyStepups,{filters:{actionRef:e,deleted:!1},limit:1});return t[0]?{actionRef:t[0].actionRef,requiredAssuranceLevel:t[0].requiredAssuranceLevel,reauthWindowSeconds:(r=t[0].reauthWindowSeconds)!=null?r:void 0}:null}async evaluateStepUp(e,t){var d;let r=await this.getActiveSessionOrThrow(e),n=await this.getStepUpRequirement(t),s=(d=n==null?void 0:n.requiredAssuranceLevel)!=null?d:"basic",o=!T(r.assuranceLevel,s);return{actionRef:t,requiredAssuranceLevel:s,currentAssuranceLevel:r.assuranceLevel,requiresStepUp:o,reauthWindowSeconds:n==null?void 0:n.reauthWindowSeconds}}async enforceStepUp(e,t){let r=await this.getActiveSessionOrThrow(e),n=await this.evaluateStepUp(e,t);if(n.requiresStepUp)throw await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_CHALLENGED",identityId:r.identityId,sessionId:e,result:"failed",reasonCode:"AUTH_STEP_UP_REQUIRED",timestamp:u()}),A("AUTH_STEP_UP_REQUIRED",`Step-up required for action '${t}' (needs ${n.requiredAssuranceLevel})`)}async markStepUpPassed(e,t){var c;let r=await this.getActiveSessionOrThrow(e),n=await this.getStepUpRequirement(t),s=(c=n==null?void 0:n.requiredAssuranceLevel)!=null?c:"elevated";await this.db.update(a.sessions,e,{assuranceLevel:s,version:r.version+1,lastModified:u()}),await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_PASSED",identityId:r.identityId,sessionId:e,result:"success",reasonCode:t,timestamp:u()});let o=await this.db.get(a.sessions,e),d=o?await v(this.db,o.activeAssignmentId):null;if(!o)throw A("AUTH_SESSION_NOT_FOUND","Session not found");return C(o,d!=null?d:void 0)}};var k=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async listAssignments(e){return(await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1},sort:[{field:"lastModified",direction:"desc"}]})).map(F)}async getActiveContext(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||!t.activeAssignmentId)return null;let r=await v(this.db,t.activeAssignmentId);return r?{sessionId:e,assignmentId:r.id,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}}:null}async switchContext(e){let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let r=null;if(e.targetAssignmentId){if(r=await v(this.db,e.targetAssignmentId),!r||r.identityId!==t.identityId)throw A("AUTH_CONTEXT_FORBIDDEN","Requested context is not assigned to this identity")}else if(e.targetTenantId){let s=await this.db.query(a.assignments,{filters:{identityId:t.identityId,tenantId:e.targetTenantId,deleted:!1},sort:[{field:"lastModified",direction:"asc"}],limit:1});if(!s[0])throw A("AUTH_CONTEXT_FORBIDDEN","No assignments found in target tenant");r=s[0]}else throw A("AUTH_CONTEXT_INVALID","Either targetAssignmentId or targetTenantId must be provided");let n=await this.db.update(a.sessions,e.sessionId,{activeAssignmentId:r.id,version:t.version+1,lastModified:u()});return await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"CONTEXT_SWITCHED",identityId:t.identityId,sessionId:e.sessionId,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}},result:"success",reasonCode:e.reasonCode,timestamp:n.lastModified}),{activeContext:{sessionId:e.sessionId,assignmentId:r.id,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}},requiresStepUp:!1,reasonCode:e.reasonCode}}};var N=class{constructor(e,t,r,n,s){this.db=e;this.options=t;this.sessionService=r;this.contextService=n;this.authAuditService=s;this.newEventId=h("auth-event")}async findIdentityByPrincipal(e){var r;return(r=(await this.db.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0])!=null?r:null}async persistFailedAttempt(e){let t=e.failedAttempts+1,r=t>=re,n=r?b(u(),ne):null,s=r?"locked":e.status;return this.db.update(a.identities,e.id,{failedAttempts:t,lockoutUntil:n,status:s,version:e.version+1,lastModified:u()})}async clearFailedAttempt(e){e.failedAttempts===0&&!e.lockoutUntil&&e.status==="active"||await this.db.update(a.identities,e.id,{failedAttempts:0,lockoutUntil:null,status:"active",version:e.version+1,lastModified:u()})}async emitAudit(e){await this.authAuditService.appendEvent(e)}async verifyCredential(e){let t=await this.findIdentityByPrincipal(e.principal);if(!t)return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",result:"failed",reasonCode:"INVALID_CREDENTIAL",timestamp:u()}),{ok:!1,reasonCode:"INVALID_CREDENTIAL",retryable:!0};if(t.status==="disabled")return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_DISABLED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_DISABLED",retryable:!1};if(t.lockoutUntil&&!E(t.lockoutUntil))return await this.emitAudit({eventId:this.newEventId(),eventType:"LOCKOUT_TRIGGERED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_LOCKED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_LOCKED",retryable:!1};if(!await oe(this.options.platformAdapter,e.secret,t.secretHash)){let o=(await this.persistFailedAttempt(t)).status==="locked"?"IDENTITY_LOCKED":"INVALID_CREDENTIAL";return await this.emitAudit({eventId:this.newEventId(),eventType:o==="IDENTITY_LOCKED"?"LOCKOUT_TRIGGERED":"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:o,timestamp:u()}),{ok:!1,reasonCode:o,retryable:o==="INVALID_CREDENTIAL"}}await this.clearFailedAttempt(t);let n=await this.contextService.listAssignments(t.id);return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_SUCCESS",identityId:t.id,scopeRef:e.scopeRef,result:"success",timestamp:u()}),{ok:!0,identity:se(t),assignments:n}}async login(e){let t=await this.verifyCredential({principal:e.principal,secret:e.secret,verifyMethod:e.verifyMethod});if(!t.ok)throw A("AUTH_INVALID_CREDENTIAL",`Authentication failed: ${t.reasonCode}`);let r=[...t.assignments].sort((s,o)=>s.assignmentId.localeCompare(o.assignmentId))[0],n=await this.sessionService.createSession({identityId:t.identity.identityId,assignmentId:r==null?void 0:r.assignmentId,assuranceLevel:"basic"});return{identity:t.identity,sessionId:n.sessionId}}async logout(e){await this.sessionService.revokeSession({sessionId:e,reasonCode:"LOGOUT"}),await this.emitAudit({eventId:this.newEventId(),eventType:"SESSION_REVOKED",sessionId:e,result:"success",reasonCode:"LOGOUT",timestamp:u()})}};var q=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-session")}async resolveGrantedAssignments(e,t){let r=await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1}});return t!=null&&t.tenantId?r.filter(n=>n.tenantId===t.tenantId):r}async createSession(e){var d,c,l,m;let t=u(),r=b(t,(d=e.ttlSeconds)!=null?d:V),n=await this.db.create(a.sessions,{id:this.newId(),identityId:e.identityId,activeAssignmentId:(c=e.assignmentId)!=null?c:null,assuranceLevel:(l=e.assuranceLevel)!=null?l:"basic",issuedAt:t,expiresAt:r,revokedAt:null,version:1,lastModified:t,deleted:!1}),s=await v(this.db,n.activeAssignmentId),o=await this.resolveGrantedAssignments(n.identityId,s);return(m=this.options.logger)==null||m.logInfo("[ofauth] session created",{sessionId:n.id,identityId:n.identityId}),C(n,s,o)}async refreshSession(e){var o;let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let r=await this.db.update(a.sessions,e.sessionId,{expiresAt:b(u(),(o=e.ttlSeconds)!=null?o:V),version:t.version+1,lastModified:u()}),n=await v(this.db,r.activeAssignmentId),s=await this.resolveGrantedAssignments(r.identityId,n);return C(r,n,s)}async revokeSession(e){var r,n;let t=await this.db.get(a.sessions,e.sessionId);!t||t.deleted||t.revokedAt||(await this.db.update(a.sessions,e.sessionId,{revokedAt:u(),version:t.version+1,lastModified:u()}),(n=this.options.logger)==null||n.logInfo("[ofauth] session revoked",{sessionId:e.sessionId,reasonCode:(r=e.reasonCode)!=null?r:null}))}async getActiveSession(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||E(t.expiresAt))return null;let r=await v(this.db,t.activeAssignmentId),n=await this.resolveGrantedAssignments(t.identityId,r);return C(t,r,n)}};async function ce(i,e={}){let t=new _(i,e),r=new q(i,e),n=new k(i,t),s=new U(i,t),o=new N(i,e,r,n,t);return{identityService:J(o),sessionService:Z(r),contextService:ee(n),authPolicyService:te(s),authAuditService:t}}function Ee(){return new Date().toISOString()}function ue(i){return`${i}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}async function Ce(i,e){return i!=null&&i.hashPin?i.hashPin(e):`sha256:${e}`}async function Pt(i){var I,R,p,w,x,W,K,j,Q,$,X,Y;let e=i.principal.trim();if(!e)throw new Error("AUTH_PROVISION_PRINCIPAL_REQUIRED");if(!((I=i.roleRef)!=null&&I.trim()))throw new Error("AUTH_PROVISION_ROLE_REQUIRED");let t=Ee(),r=await Ce(i.platformAdapter,i.secret),n=i.dbAdapter,o=(await n.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0],d=(R=o==null?void 0:o.id)!=null?R:ue("ofauth-identity");o?await n.update(a.identities,d,{secretHash:r,status:"active",lastModified:t}):await n.create(a.identities,{id:d,principal:e,secretHash:r,verifyMethod:"pin",status:"active",failedAttempts:0,lockoutUntil:null,version:1,lastModified:t,deleted:!1});let l=(await n.query(a.assignments,{filters:{identityId:d,deleted:!1},limit:1}))[0],m=(p=l==null?void 0:l.id)!=null?p:ue("ofauth-assignment"),g={source:(w=i.source)!=null?w:"host-app"};return l?await n.update(a.assignments,m,{roleRef:i.roleRef,tenantId:(W=(x=i.scope)==null?void 0:x.tenantId)!=null?W:null,branchId:(j=(K=i.scope)==null?void 0:K.branchId)!=null?j:null,scopeAttributes:g,lastModified:t}):await n.create(a.assignments,{id:m,identityId:d,roleRef:i.roleRef,tenantId:($=(Q=i.scope)==null?void 0:Q.tenantId)!=null?$:null,branchId:(Y=(X=i.scope)==null?void 0:X.branchId)!=null?Y:null,scopeAttributes:g,version:1,lastModified:t,deleted:!1}),{identityId:d,assignmentId:m}}var Dt="phase2-runtime-logic";import{CoreRuntime as be}from"ofcore";import{InMemoryDbAdapter as me}from"ofcore";import{asReadonlyStore as xe,createStore as Te}from"ofcore";var le=[{toVersion:1,up:async i=>{let e=ie();for(let t of e)try{await i.addTable(t)}catch{}}}];var we={logInfo(){},logWarn(){},logError(){}};async function pe(i,e=we){e.logInfo("[ofauth] starting database migration process");let t=[...le].sort((s,o)=>s.toVersion-o.toVersion),r=t.length>0?t[t.length-1].toVersion:0,n=await i.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){e.logInfo(`[ofauth] database already up-to-date at v${n}`);return}for(let s of t)s.toVersion>n&&(e.logInfo(`[ofauth] applying migration v${s.toVersion}`),await s.up(i),await i.setSchemaVersion(s.toVersion),n=s.toVersion);e.logInfo(`[ofauth] migration completed at v${n}`)}var B=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=xe(this.runtimeStateStore)}static builder(){return new G}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.start(e),this.domainServices=fe(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async init(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.init(e),this.domainServices=fe(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async stop(){this.runtimeStateStore.setState({phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState({phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()}),e}}isStarted(){return this.runtime.isStarted()}};function fe(i){if(!i)throw new Error("Ofauth runtime started without domain services");return i}var G=class{constructor(){this.runtimeBuilder=be.builder();this.domainServiceOverrides={};this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new me)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}overrideDomainServices(e){return this.domainServiceOverrides={...this.domainServiceOverrides,...e},this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}withMigrationRunner(e){return this.withRuntimeHooks({runMigrations:e})}build(){var n;let e=Te({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t=async s=>{var d,c;let o=(d=s.registry)==null?void 0:d.dbAdapter;o&&await pe(o,(c=s.registry)==null?void 0:c.loggerAdapter)};this.runtimeBuilder.withHooks({...this.runtimeHooks,runMigrations:(n=this.runtimeHooks.runMigrations)!=null?n:t,createDomainServices:async s=>{var d,c,l,m;return{...this.domainServicesFactory?await this.domainServicesFactory():await ce((c=(d=s.registry)==null?void 0:d.dbAdapter)!=null?c:new me,{logger:(l=s.registry)==null?void 0:l.loggerAdapter,platformAdapter:(m=s.registry)==null?void 0:m.platformAdapter,emitActivity:async g=>{await s.emitActivity(g)}}),...this.domainServiceOverrides}}});let r=this.runtimeBuilder.build();return new B(r,e)}};export{D as AuthRejectionError,P as DefaultAuthOfflinePolicy,Dt as OFAUTH_CONTRACT_STAGE,a as OFAUTH_TABLES,B as OfauthCore,G as OfauthCoreBuilder,L as OfauthDomainError,pe as applyPendingMigrations,Qe as createContractOnlyOfauthServices,ce as createDbAdapterOfauthServices,Ke as createServerAuthoritativeAuthBridge,He as evaluateProtectedRouteGate,ie as getOfauthTableSchemas,Oe as hasAnyScopeDimension,Fe as invalidState,T as isAssuranceLevelAtLeast,De as isAuthAuditEventType,ke as loginWithResolvedContext,y as mapAuthErrorToEnvelope,le as migrations,ge as ofauthSchema,Ne as refreshResolvedContext,qe as switchContextWithResolvedState,M as toAuthFailureEnvelope,f as toAuthSuccessEnvelope,A as unauthorized,Pt as upsertLocalIdentityAndAssignment};
|
|
1
|
+
function De(n){return!!(n.tenantId||n.branchId||n.attributes&&Object.keys(n.attributes).length>0)}function T(n,e){let t={basic:1,elevated:2};return t[n]>=t[e]}function ke(n){return["LOGIN_SUCCESS","LOGIN_FAILED","LOCKOUT_TRIGGERED","SESSION_REVOKED","CONTEXT_SWITCHED","STEP_UP_CHALLENGED","STEP_UP_PASSED","STEP_UP_FAILED"].includes(n)}function Z(n,e){if(e)return n.find(t=>t.assignmentId===e)}function Ae(n,e,t){var i,r;return(r=(i=Z(n,t))!=null?i:Z(n,e))!=null?r:n[0]}function he(n,e){var t;if(e.requiredTenantId&&n.tenantId!==e.requiredTenantId||e.requiredBranchId&&n.branchId!==e.requiredBranchId)return!1;if(e.requiredScopeAttributes){let i=(t=n.attributes)!=null?t:{};for(let[r,s]of Object.entries(e.requiredScopeAttributes))if(i[r]!==s)return!1}return!0}function H(n){if(typeof n!="string")return null;let e=n.trim();return e.length>0?e:null}function O(n){var e;if(n&&typeof n=="object"&&n.error&&typeof n.error.code=="string"){let t=new Error(n.error.message||n.error.code);throw t.code=n.error.code,t}return(e=n==null?void 0:n.data)!=null?e:n}async function M(n,e){var o,d,c;let t=O(await n.sessionService.getActiveSession(e.sessionId));if(!t)return null;let i=O(await n.contextService.listAssignments(e.identityId)),r=O(await n.contextService.getActiveContext(e.sessionId)),s=Ae(i,r==null?void 0:r.assignmentId,e.preferredAssignmentId);return{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,assignments:i,activeContextAssignmentId:s==null?void 0:s.assignmentId,activeAssignment:s,scopeRef:(c=(d=(o=s==null?void 0:s.scopeRef)!=null?o:r==null?void 0:r.scopeRef)!=null?d:t.activeScopeRef)!=null?c:{},roleRef:s==null?void 0:s.roleRef,assuranceLevel:t.assuranceLevel}}function ve(n){var e,t,i,r,s,o,d;return{assignmentStatus:n.assignmentId?"assigned":"unassigned",activeAssignmentId:(e=n.assignmentId)!=null?e:null,activeRoleRef:(t=n.roleRef)!=null?t:null,activeTenantId:H((i=n.scopeRef)==null?void 0:i.tenantId),activeBranchId:H((r=n.scopeRef)==null?void 0:r.branchId),activeDomainId:H((o=(s=n.scopeRef)==null?void 0:s.attributes)==null?void 0:o.domainId),assuranceLevel:(d=n.assuranceLevel)!=null?d:null}}function He(n){var e,t,i,r,s;return n?[`assignment=${(e=n.activeAssignmentId)!=null?e:n.assignmentStatus}`,`tenant=${(t=n.activeTenantId)!=null?t:"-"}`,`branch=${(i=n.activeBranchId)!=null?i:"-"}`,`domain=${(r=n.activeDomainId)!=null?r:"-"}`,`assurance=${(s=n.assuranceLevel)!=null?s:"-"}`].join(" | "):"assignment=unassigned | tenant=- | branch=- | domain=- | assurance=-"}function Me(n){var e;return n?ve({scopeRef:n.scopeRef,roleRef:n.roleRef,assuranceLevel:n.assuranceLevel,assignmentId:(e=n.activeContextAssignmentId)!=null?e:null}):null}async function Ve(n,e){let t=O(await n.identityService.login(e.principal,e.secret,e.scopeRef)),i=await M(n,{sessionId:t.sessionId,identityId:t.identity.identityId,principal:t.identity.principal});if(!i)throw new Error("session is not active after login");return i}async function Fe(n,e){return M(n,e)}async function Be(n,e){let t=await M(n,{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,preferredAssignmentId:e.targetAssignmentId});if(!t)throw new Error("session is not active while switching context");if(t.activeContextAssignmentId!==e.targetAssignmentId)throw new Error("requested assignment is not available for the active identity");return t}function Ge(n,e={}){var i,r;if(!n)return{allowed:!1,reasonCode:"NO_SESSION"};let t=(i=e.minimumAssuranceLevel)!=null?i:"basic";return T(n.assuranceLevel,t)?(r=e.requiredRoleRefs)!=null&&r.length&&!(!!n.roleRef&&e.requiredRoleRefs.includes(n.roleRef))?{allowed:!1,reasonCode:"ROLE_FORBIDDEN"}:he(n.scopeRef,e)?{allowed:!0}:{allowed:!1,reasonCode:"SCOPE_FORBIDDEN"}:{allowed:!1,reasonCode:"ASSURANCE_TOO_LOW"}}var P=class{canLoginOffline(e){let t=new Date(e.nowIso).getTime(),i=new Date(e.envelope.expiresAt).getTime();return!Number.isFinite(t)||!Number.isFinite(i)?!1:t<=i}};var L=class extends Error{constructor(t,i,r=!1){super(i);this.code=t;this.retryable=r;this.name="OfauthDomainError"}},D=class extends Error{constructor(t){super(t);this.code=t;this.name="AuthRejectionError"}};function A(n,e){return new L(n,e,!1)}function Ke(n){return new L("AUTH_NOT_IMPLEMENTED",n,!1)}var ge=new Set(["AUTH_UNAUTHORIZED","AUTH_INVALID_CREDENTIAL","AUTH_LOCKED","AUTH_DISABLED"]);function Ie(n){var e;return{principal:n.principal,accessToken:n.accessToken,refreshToken:n.refreshToken,assuranceLevel:n.assuranceLevel,issuedAt:n.issuedAt,expiresAt:n.expiresAt,activeRoleRef:n.activeRoleRef,activeContext:(e=n.activeContext)!=null?e:null}}function Xe(n){var r,s,o;let e=(r=n.now)!=null?r:(()=>new Date().toISOString()),t=(s=n.isOnline)!=null?s:(()=>!0),i=(o=n.offlinePolicy)!=null?o:new P;return{async login(d){var I,R;let c=String(d.principal||"").trim();if(!c)return{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"};if(t())try{let p=await n.authority.login(d),w=Ie({principal:c,accessToken:p.accessToken,refreshToken:p.refreshToken,assuranceLevel:p.session.assuranceLevel,issuedAt:p.session.issuedAt,expiresAt:p.session.expiresAt,activeRoleRef:p.activeRoleRef,activeContext:(I=p.activeContext)!=null?I:null}),x={principal:c,identityId:p.session.identityId,roleRef:(R=p.activeRoleRef)!=null?R:null,lastOnlineAuthAt:e()};return await n.cache.setCachedIdentity(x),await n.cache.setSessionEnvelope(c,w),{status:"authenticated",mode:"online",session:w}}catch(p){return p instanceof D?{status:"rejected",reasonCode:p.code}:p instanceof Error&&ge.has(p.message)?{status:"rejected",reasonCode:p.message}:{status:"rejected",reasonCode:"AUTH_AUTHORITY_UNAVAILABLE"}}let l=await n.cache.getCachedIdentity(c),m=await n.cache.getSessionEnvelope(c);return!l||!m?{status:"rejected",reasonCode:"OFFLINE_SESSION_NOT_AVAILABLE"}:i.canLoginOffline({nowIso:e(),envelope:m})?await n.verifyOfflineSecret({principal:c,secret:d.secret})?{status:"authenticated",mode:"offline",session:m}:{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"}:{status:"rejected",reasonCode:"OFFLINE_SESSION_EXPIRED"}},async logout(d){let c=await n.cache.getSessionEnvelope(d);if(c)try{await n.authority.logout({accessToken:c.accessToken,refreshToken:c.refreshToken})}catch{}}}}function S(n){return{error:{code:"AUTH_NOT_IMPLEMENTED",message:n,retryable:!1}}}function Je(){return{identityService:{async verifyCredential(){return S("identityService.verifyCredential not implemented yet")},async login(n,e){return S("identityService.login not implemented yet")},async logout(){return S("identityService.logout not implemented yet")}},sessionService:{async createSession(){return S("sessionService.createSession not implemented yet")},async refreshSession(){return S("sessionService.refreshSession not implemented yet")},async revokeSession(){return S("sessionService.revokeSession not implemented yet")},async getActiveSession(){return S("sessionService.getActiveSession not implemented yet")}},contextService:{async listAssignments(){return S("contextService.listAssignments not implemented yet")},async getActiveContext(){return S("contextService.getActiveContext not implemented yet")},async switchContext(){return S("contextService.switchContext not implemented yet")}},authPolicyService:{async getPolicySnapshot(){return S("authPolicyService.getPolicySnapshot not implemented yet")},async getStepUpRequirement(){return S("authPolicyService.getStepUpRequirement not implemented yet")},async evaluateStepUp(){return S("authPolicyService.evaluateStepUp not implemented yet")},async enforceStepUp(){return S("authPolicyService.enforceStepUp not implemented yet")},async markStepUpPassed(){return S("authPolicyService.markStepUpPassed not implemented yet")}},authAuditService:{async appendEvent(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.appendEvent not implemented yet",retryable:!1}},async queryEvents(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.queryEvents not implemented yet",retryable:!1}},async listPendingReplay(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.listPendingReplay not implemented yet",retryable:!1}},async markReplayed(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.markReplayed not implemented yet",retryable:!1}}}}}function f(n,e){return{data:n,meta:{request_id:e!=null?e:null,timestamp:new Date().toISOString()}}}function V(n,e,t={}){var i;return{error:{code:n,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:(i=t.requestId)!=null?i:null,timestamp:new Date().toISOString()}}}function y(n,e="AUTH_NOT_IMPLEMENTED",t="Unhandled auth error."){var i;if(n&&typeof n=="object"){let r=n;return V((i=r.code)!=null?i:e,r.message||t,{retryable:r.retryable})}return n instanceof Error?V(e,n.message||t):V(e,t)}function ee(n){return{async verifyCredential(e){try{return f(await n.verifyCredential(e))}catch(t){return y(t)}},async login(e,t,i){try{let r=await n.login({principal:e,secret:t,verifyMethod:"password"});return f(r)}catch(r){return y(r)}},async logout(e){try{return await n.logout(e),f({sessionId:e,revoked:!0})}catch(t){return y(t)}}}}function te(n){return{async createSession(e){try{return f(await n.createSession(e))}catch(t){return y(t)}},async refreshSession(e){try{return f(await n.refreshSession(e))}catch(t){return y(t)}},async revokeSession(e){try{return await n.revokeSession(e),f({sessionId:e.sessionId,revoked:!0})}catch(t){return y(t)}},async getActiveSession(e){try{return f(await n.getActiveSession(e))}catch(t){return y(t)}}}}function ne(n){return{async listAssignments(e){try{return f(await n.listAssignments(e))}catch(t){return y(t)}},async getActiveContext(e){try{return f(await n.getActiveContext(e))}catch(t){return y(t)}},async switchContext(e){try{return f(await n.switchContext(e))}catch(t){return y(t)}}}}function ie(n){return{async getPolicySnapshot(){try{return f(await n.getPolicySnapshot())}catch(e){return y(e)}},async getStepUpRequirement(e){try{return f(await n.getStepUpRequirement(e))}catch(t){return y(t)}},async evaluateStepUp(e,t){try{return f(await n.evaluateStepUp(e,t))}catch(i){return y(i)}},async enforceStepUp(e,t){try{return await n.enforceStepUp(e,t),f({sessionId:e,actionRef:t,enforced:!0})}catch(i){return y(i)}},async markStepUpPassed(e,t){try{return f(await n.markStepUpPassed(e,t))}catch(i){return y(i)}}}}var a={identities:"ofauth_identities",assignments:"ofauth_assignments",sessions:"ofauth_sessions",policyProfiles:"ofauth_policy_profiles",policyStepups:"ofauth_policy_stepups",auditEvents:"ofauth_audit_events"},Re=[{name:a.identities,columns:[{name:"id",type:"string"},{name:"principal",type:"string",isIndexed:!0},{name:"secretHash",type:"string"},{name:"verifyMethod",type:"string",enum:["pin","password","custom"]},{name:"status",type:"string",enum:["active","disabled","locked"],isIndexed:!0},{name:"failedAttempts",type:"number"},{name:"lockoutUntil",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.assignments,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"roleRef",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.sessions,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"activeAssignmentId",type:"string",isOptional:!0,isIndexed:!0},{name:"assuranceLevel",type:"string",enum:["basic","elevated"],isIndexed:!0},{name:"issuedAt",type:"string"},{name:"expiresAt",type:"string",isIndexed:!0},{name:"revokedAt",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyProfiles,columns:[{name:"id",type:"string"},{name:"profileId",type:"string",isIndexed:!0},{name:"defaultAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"lockoutPolicyRef",type:"string"},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyStepups,columns:[{name:"id",type:"string"},{name:"actionRef",type:"string",isIndexed:!0},{name:"requiredAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"reauthWindowSeconds",type:"number",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.auditEvents,columns:[{name:"id",type:"string"},{name:"eventType",type:"string",isIndexed:!0},{name:"identityId",type:"string",isOptional:!0,isIndexed:!0},{name:"sessionId",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"result",type:"string",enum:["success","failed"],isIndexed:!0},{name:"reasonCode",type:"string",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"syncStatus",type:"string",enum:["pending","replayed"],isIndexed:!0},{name:"replayedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]}],Ce={version:2,tables:Re};function re(){return Ce.tables}import{makeIdFactory as Ee,nowIso as we}from"ofcore";var se=5,oe=900,F=480*60;function u(){return we()}function b(n,e){return new Date(new Date(n).getTime()+e*1e3).toISOString()}function C(n){return new Date(n).getTime()<=Date.now()}function h(n){return Ee(n)}function ae(n){return{identityId:n.id,principal:n.principal,status:n.status}}function B(n){return{assignmentId:n.id,identityId:n.identityId,roleRef:n.roleRef,scopeRef:{...n.tenantId?{tenantId:n.tenantId}:{},...n.branchId?{branchId:n.branchId}:{},...n.scopeAttributes?{attributes:n.scopeAttributes}:{}}}}function E(n,e,t){return{sessionId:n.id,identityId:n.identityId,activeScopeRef:e?{...e.tenantId?{tenantId:e.tenantId}:{},...e.branchId?{branchId:e.branchId}:{},...e.scopeAttributes?{attributes:e.scopeAttributes}:{}}:void 0,grantedAssignments:t!==void 0?t.map(B):void 0,assuranceLevel:n.assuranceLevel,issuedAt:n.issuedAt,expiresAt:n.expiresAt}}async function de(n,e,t){return n?n.verifyPin(e,t):e===t}async function ce(n,e){var t,i,r,s,o,d;n.emitActivity&&await n.emitActivity({activityId:e.eventId,activityType:`ofauth.${e.eventType.toLowerCase()}`,occurredAt:e.timestamp,scopeRef:{domain:"ofauth",...(t=e.scopeRef)!=null&&t.tenantId?{tenantId:e.scopeRef.tenantId}:{},...(i=e.scopeRef)!=null&&i.branchId?{branchId:e.scopeRef.branchId}:{}},actor:e.identityId?{userId:e.identityId}:void 0,payload:{eventType:e.eventType,result:e.result,reasonCode:(r=e.reasonCode)!=null?r:null,sessionId:(s=e.sessionId)!=null?s:null,scopeAttributes:(d=(o=e.scopeRef)==null?void 0:o.attributes)!=null?d:null}})}async function v(n,e){if(!e)return null;let t=await n.get(a.assignments,e);return!t||t.deleted?null:t}function ue(){return[{profileId:"cashier_fast",defaultAssuranceLevel:"basic",lockoutPolicyRef:"default"},{profileId:"supervisor_strict",defaultAssuranceLevel:"elevated",lockoutPolicyRef:"strict"},{profileId:"member_self_service",defaultAssuranceLevel:"basic",lockoutPolicyRef:"member"}]}function G(){return[{actionRef:"auth.device_identity_revoke",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300},{actionRef:"auth.device_identity_reissue",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300},{actionRef:"auth.assignment_revoke",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300}]}var _=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-audit")}async appendEvent(e){var i,r,s,o,d,c,l,m,g,I,R;let t={id:e.eventId||this.newId(),eventType:e.eventType,identityId:(i=e.identityId)!=null?i:null,sessionId:(r=e.sessionId)!=null?r:null,tenantId:(o=(s=e.scopeRef)==null?void 0:s.tenantId)!=null?o:null,branchId:(c=(d=e.scopeRef)==null?void 0:d.branchId)!=null?c:null,scopeAttributes:(m=(l=e.scopeRef)==null?void 0:l.attributes)!=null?m:null,result:e.result,reasonCode:(g=e.reasonCode)!=null?g:null,timestamp:e.timestamp,syncStatus:(I=e.syncStatus)!=null?I:"pending",replayedAt:(R=e.replayedAt)!=null?R:null,version:1,lastModified:u(),deleted:!1};await this.db.create(a.auditEvents,t),await ce(this.options,e)}async queryEvents(e){return(await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"desc"}]})).filter(i=>e.identityId?i.identityId===e.identityId:!0).filter(i=>e.sessionId?i.sessionId===e.sessionId:!0).filter(i=>{var r;return(r=e.eventTypes)!=null&&r.length?e.eventTypes.includes(i.eventType):!0}).filter(i=>e.fromTimestamp?i.timestamp>=e.fromTimestamp:!0).filter(i=>e.toTimestamp?i.timestamp<=e.toTimestamp:!0).map(i=>{var r,s,o,d,c;return{eventId:i.id,eventType:i.eventType,identityId:(r=i.identityId)!=null?r:void 0,sessionId:(s=i.sessionId)!=null?s:void 0,scopeRef:i.tenantId||i.branchId||i.scopeAttributes?{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}:void 0,result:i.result,reasonCode:(o=i.reasonCode)!=null?o:void 0,timestamp:i.timestamp,syncStatus:(d=i.syncStatus)!=null?d:"pending",replayedAt:(c=i.replayedAt)!=null?c:void 0}})}async listPendingReplay(e={}){var i;let t=await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"asc"}]});return t.filter(r=>r.syncStatus!=="replayed").slice(0,(i=e.limit)!=null?i:t.length).map(r=>{var s,o,d,c,l;return{eventId:r.id,eventType:r.eventType,identityId:(s=r.identityId)!=null?s:void 0,sessionId:(o=r.sessionId)!=null?o:void 0,scopeRef:r.tenantId||r.branchId||r.scopeAttributes?{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}:void 0,result:r.result,reasonCode:(d=r.reasonCode)!=null?d:void 0,timestamp:r.timestamp,syncStatus:(c=r.syncStatus)!=null?c:"pending",replayedAt:(l=r.replayedAt)!=null?l:void 0}})}async markReplayed(e,t=u()){let i=0;for(let r of e){let s=await this.db.get(a.auditEvents,r);!s||s.deleted||s.syncStatus==="replayed"||(await this.db.update(a.auditEvents,r,{syncStatus:"replayed",replayedAt:t,version:s.version+1,lastModified:u()}),i+=1)}return i}};var U=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async getActiveSessionOrThrow(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||C(t.expiresAt))throw A("AUTH_SESSION_NOT_FOUND","Session not found");return t}async getPolicySnapshot(){var s;let e=await this.db.query(a.policyProfiles,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),t=await this.db.query(a.policyStepups,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),i=G(),r=new Map(i.map(o=>[o.actionRef,o]));for(let o of t)r.set(o.actionRef,{actionRef:o.actionRef,requiredAssuranceLevel:o.requiredAssuranceLevel,reauthWindowSeconds:(s=o.reauthWindowSeconds)!=null?s:void 0});return{profiles:e.length>0?e.map(o=>({profileId:o.profileId,defaultAssuranceLevel:o.defaultAssuranceLevel,lockoutPolicyRef:o.lockoutPolicyRef})):ue(),stepUpRequirements:Array.from(r.values()),version:"1",updatedAt:u()}}async getStepUpRequirement(e){var i,r;let t=await this.db.query(a.policyStepups,{filters:{actionRef:e,deleted:!1},limit:1});return t[0]?{actionRef:t[0].actionRef,requiredAssuranceLevel:t[0].requiredAssuranceLevel,reauthWindowSeconds:(r=t[0].reauthWindowSeconds)!=null?r:void 0}:(i=G().find(s=>s.actionRef===e))!=null?i:null}async evaluateStepUp(e,t){var d;let i=await this.getActiveSessionOrThrow(e),r=await this.getStepUpRequirement(t),s=(d=r==null?void 0:r.requiredAssuranceLevel)!=null?d:"basic",o=!T(i.assuranceLevel,s);return{actionRef:t,requiredAssuranceLevel:s,currentAssuranceLevel:i.assuranceLevel,requiresStepUp:o,reauthWindowSeconds:r==null?void 0:r.reauthWindowSeconds}}async enforceStepUp(e,t){let i=await this.getActiveSessionOrThrow(e),r=await this.evaluateStepUp(e,t);if(r.requiresStepUp)throw await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_CHALLENGED",identityId:i.identityId,sessionId:e,result:"failed",reasonCode:"AUTH_STEP_UP_REQUIRED",timestamp:u()}),A("AUTH_STEP_UP_REQUIRED",`Step-up required for action '${t}' (needs ${r.requiredAssuranceLevel})`)}async markStepUpPassed(e,t){var c;let i=await this.getActiveSessionOrThrow(e),r=await this.getStepUpRequirement(t),s=(c=r==null?void 0:r.requiredAssuranceLevel)!=null?c:"elevated";await this.db.update(a.sessions,e,{assuranceLevel:s,version:i.version+1,lastModified:u()}),await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_PASSED",identityId:i.identityId,sessionId:e,result:"success",reasonCode:t,timestamp:u()});let o=await this.db.get(a.sessions,e),d=o?await v(this.db,o.activeAssignmentId):null;if(!o)throw A("AUTH_SESSION_NOT_FOUND","Session not found");return E(o,d!=null?d:void 0)}};var k=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async listAssignments(e){return(await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1},sort:[{field:"lastModified",direction:"desc"}]})).map(B)}async getActiveContext(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||!t.activeAssignmentId)return null;let i=await v(this.db,t.activeAssignmentId);return i?{sessionId:e,assignmentId:i.id,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}}:null}async switchContext(e){let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let i=null;if(e.targetAssignmentId){if(i=await v(this.db,e.targetAssignmentId),!i||i.identityId!==t.identityId)throw A("AUTH_CONTEXT_FORBIDDEN","Requested context is not assigned to this identity")}else if(e.targetTenantId){let s=await this.db.query(a.assignments,{filters:{identityId:t.identityId,tenantId:e.targetTenantId,deleted:!1},sort:[{field:"lastModified",direction:"asc"}],limit:1});if(!s[0])throw A("AUTH_CONTEXT_FORBIDDEN","No assignments found in target tenant");i=s[0]}else throw A("AUTH_CONTEXT_INVALID","Either targetAssignmentId or targetTenantId must be provided");let r=await this.db.update(a.sessions,e.sessionId,{activeAssignmentId:i.id,version:t.version+1,lastModified:u()});return await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"CONTEXT_SWITCHED",identityId:t.identityId,sessionId:e.sessionId,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}},result:"success",reasonCode:e.reasonCode,timestamp:r.lastModified}),{activeContext:{sessionId:e.sessionId,assignmentId:i.id,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}},requiresStepUp:!1,reasonCode:e.reasonCode}}};var N=class{constructor(e,t,i,r,s){this.db=e;this.options=t;this.sessionService=i;this.contextService=r;this.authAuditService=s;this.newEventId=h("auth-event")}async findIdentityByPrincipal(e){var i;return(i=(await this.db.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0])!=null?i:null}async persistFailedAttempt(e){let t=e.failedAttempts+1,i=t>=se,r=i?b(u(),oe):null,s=i?"locked":e.status;return this.db.update(a.identities,e.id,{failedAttempts:t,lockoutUntil:r,status:s,version:e.version+1,lastModified:u()})}async clearFailedAttempt(e){e.failedAttempts===0&&!e.lockoutUntil&&e.status==="active"||await this.db.update(a.identities,e.id,{failedAttempts:0,lockoutUntil:null,status:"active",version:e.version+1,lastModified:u()})}async emitAudit(e){await this.authAuditService.appendEvent(e)}async verifyCredential(e){let t=await this.findIdentityByPrincipal(e.principal);if(!t)return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",result:"failed",reasonCode:"INVALID_CREDENTIAL",timestamp:u()}),{ok:!1,reasonCode:"INVALID_CREDENTIAL",retryable:!0};if(t.status==="disabled")return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_DISABLED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_DISABLED",retryable:!1};if(t.lockoutUntil&&!C(t.lockoutUntil))return await this.emitAudit({eventId:this.newEventId(),eventType:"LOCKOUT_TRIGGERED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_LOCKED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_LOCKED",retryable:!1};if(!await de(this.options.platformAdapter,e.secret,t.secretHash)){let o=(await this.persistFailedAttempt(t)).status==="locked"?"IDENTITY_LOCKED":"INVALID_CREDENTIAL";return await this.emitAudit({eventId:this.newEventId(),eventType:o==="IDENTITY_LOCKED"?"LOCKOUT_TRIGGERED":"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:o,timestamp:u()}),{ok:!1,reasonCode:o,retryable:o==="INVALID_CREDENTIAL"}}await this.clearFailedAttempt(t);let r=await this.contextService.listAssignments(t.id);return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_SUCCESS",identityId:t.id,scopeRef:e.scopeRef,result:"success",timestamp:u()}),{ok:!0,identity:ae(t),assignments:r}}async login(e){let t=await this.verifyCredential({principal:e.principal,secret:e.secret,verifyMethod:e.verifyMethod});if(!t.ok)throw A("AUTH_INVALID_CREDENTIAL",`Authentication failed: ${t.reasonCode}`);let i=[...t.assignments].sort((s,o)=>s.assignmentId.localeCompare(o.assignmentId))[0],r=await this.sessionService.createSession({identityId:t.identity.identityId,assignmentId:i==null?void 0:i.assignmentId,assuranceLevel:"basic"});return{identity:t.identity,sessionId:r.sessionId}}async logout(e){await this.sessionService.revokeSession({sessionId:e,reasonCode:"LOGOUT"}),await this.emitAudit({eventId:this.newEventId(),eventType:"SESSION_REVOKED",sessionId:e,result:"success",reasonCode:"LOGOUT",timestamp:u()})}};var q=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-session")}async resolveGrantedAssignments(e,t){let i=await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1}});return t!=null&&t.tenantId?i.filter(r=>r.tenantId===t.tenantId):i}async createSession(e){var d,c,l,m;let t=u(),i=b(t,(d=e.ttlSeconds)!=null?d:F),r=await this.db.create(a.sessions,{id:this.newId(),identityId:e.identityId,activeAssignmentId:(c=e.assignmentId)!=null?c:null,assuranceLevel:(l=e.assuranceLevel)!=null?l:"basic",issuedAt:t,expiresAt:i,revokedAt:null,version:1,lastModified:t,deleted:!1}),s=await v(this.db,r.activeAssignmentId),o=await this.resolveGrantedAssignments(r.identityId,s);return(m=this.options.logger)==null||m.logInfo("[ofauth] session created",{sessionId:r.id,identityId:r.identityId}),E(r,s,o)}async refreshSession(e){var o;let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let i=await this.db.update(a.sessions,e.sessionId,{expiresAt:b(u(),(o=e.ttlSeconds)!=null?o:F),version:t.version+1,lastModified:u()}),r=await v(this.db,i.activeAssignmentId),s=await this.resolveGrantedAssignments(i.identityId,r);return E(i,r,s)}async revokeSession(e){var i,r;let t=await this.db.get(a.sessions,e.sessionId);!t||t.deleted||t.revokedAt||(await this.db.update(a.sessions,e.sessionId,{revokedAt:u(),version:t.version+1,lastModified:u()}),(r=this.options.logger)==null||r.logInfo("[ofauth] session revoked",{sessionId:e.sessionId,reasonCode:(i=e.reasonCode)!=null?i:null}))}async getActiveSession(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||C(t.expiresAt))return null;let i=await v(this.db,t.activeAssignmentId),r=await this.resolveGrantedAssignments(t.identityId,i);return E(t,i,r)}};async function le(n,e={}){let t=new _(n,e),i=new q(n,e),r=new k(n,t),s=new U(n,t),o=new N(n,e,i,r,t);return{identityService:ee(o),sessionService:te(i),contextService:ne(r),authPolicyService:ie(s),authAuditService:t}}function be(){return new Date().toISOString()}function pe(n){return`${n}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}async function xe(n,e){return n!=null&&n.hashPin?n.hashPin(e):`sha256:${e}`}async function kt(n){var I,R,p,w,x,K,$,Q,z,X,Y,J;let e=n.principal.trim();if(!e)throw new Error("AUTH_PROVISION_PRINCIPAL_REQUIRED");if(!((I=n.roleRef)!=null&&I.trim()))throw new Error("AUTH_PROVISION_ROLE_REQUIRED");let t=be(),i=await xe(n.platformAdapter,n.secret),r=n.dbAdapter,o=(await r.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0],d=(R=o==null?void 0:o.id)!=null?R:pe("ofauth-identity");o?await r.update(a.identities,d,{secretHash:i,status:"active",lastModified:t}):await r.create(a.identities,{id:d,principal:e,secretHash:i,verifyMethod:"pin",status:"active",failedAttempts:0,lockoutUntil:null,version:1,lastModified:t,deleted:!1});let l=(await r.query(a.assignments,{filters:{identityId:d,deleted:!1},limit:1}))[0],m=(p=l==null?void 0:l.id)!=null?p:pe("ofauth-assignment"),g={source:(w=n.source)!=null?w:"host-app"};return l?await r.update(a.assignments,m,{roleRef:n.roleRef,tenantId:(K=(x=n.scope)==null?void 0:x.tenantId)!=null?K:null,branchId:(Q=($=n.scope)==null?void 0:$.branchId)!=null?Q:null,scopeAttributes:g,lastModified:t}):await r.create(a.assignments,{id:m,identityId:d,roleRef:n.roleRef,tenantId:(X=(z=n.scope)==null?void 0:z.tenantId)!=null?X:null,branchId:(J=(Y=n.scope)==null?void 0:Y.branchId)!=null?J:null,scopeAttributes:g,version:1,lastModified:t,deleted:!1}),{identityId:d,assignmentId:m}}var qt="phase2-runtime-logic";import{CoreRuntime as Oe}from"ofcore";import{InMemoryDbAdapter as ye}from"ofcore";import{asReadonlyStore as Pe,createStore as Le}from"ofcore";var me=[{toVersion:1,up:async n=>{let e=re();for(let t of e)try{await n.addTable(t)}catch{}}}];var Te={logInfo(){},logWarn(){},logError(){}};async function fe(n,e=Te){e.logInfo("[ofauth] starting database migration process");let t=[...me].sort((s,o)=>s.toVersion-o.toVersion),i=t.length>0?t[t.length-1].toVersion:0,r=await n.getSchemaVersion();if((r==null||r<0)&&(r=0),r>=i){e.logInfo(`[ofauth] database already up-to-date at v${r}`);return}for(let s of t)s.toVersion>r&&(e.logInfo(`[ofauth] applying migration v${s.toVersion}`),await s.up(n),await n.setSchemaVersion(s.toVersion),r=s.toVersion);e.logInfo(`[ofauth] migration completed at v${r}`)}var W=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=Pe(this.runtimeStateStore)}static builder(){return new j}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.start(e),this.domainServices=Se(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async init(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.init(e),this.domainServices=Se(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async stop(){this.runtimeStateStore.setState({phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState({phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()}),e}}isStarted(){return this.runtime.isStarted()}};function Se(n){if(!n)throw new Error("Ofauth runtime started without domain services");return n}var j=class{constructor(){this.runtimeBuilder=Oe.builder();this.domainServiceOverrides={};this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new ye)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}overrideDomainServices(e){return this.domainServiceOverrides={...this.domainServiceOverrides,...e},this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}withMigrationRunner(e){return this.withRuntimeHooks({runMigrations:e})}build(){var r;let e=Le({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t=async s=>{var d,c;let o=(d=s.registry)==null?void 0:d.dbAdapter;o&&await fe(o,(c=s.registry)==null?void 0:c.loggerAdapter)};this.runtimeBuilder.withHooks({...this.runtimeHooks,runMigrations:(r=this.runtimeHooks.runMigrations)!=null?r:t,createDomainServices:async s=>{var d,c,l,m;return{...this.domainServicesFactory?await this.domainServicesFactory():await le((c=(d=s.registry)==null?void 0:d.dbAdapter)!=null?c:new ye,{logger:(l=s.registry)==null?void 0:l.loggerAdapter,platformAdapter:(m=s.registry)==null?void 0:m.platformAdapter,emitActivity:async g=>{await s.emitActivity(g)}}),...this.domainServiceOverrides}}});let i=this.runtimeBuilder.build();return new W(i,e)}};export{D as AuthRejectionError,P as DefaultAuthOfflinePolicy,qt as OFAUTH_CONTRACT_STAGE,a as OFAUTH_TABLES,W as OfauthCore,j as OfauthCoreBuilder,L as OfauthDomainError,fe as applyPendingMigrations,Je as createContractOnlyOfauthServices,le as createDbAdapterOfauthServices,Xe as createServerAuthoritativeAuthBridge,Ge as evaluateProtectedRouteGate,He as formatAuthContextSummary,re as getOfauthTableSchemas,De as hasAnyScopeDimension,Ke as invalidState,T as isAssuranceLevelAtLeast,ke as isAuthAuditEventType,Ve as loginWithResolvedContext,y as mapAuthErrorToEnvelope,me as migrations,Ce as ofauthSchema,Fe as refreshResolvedContext,ve as summarizeAuthScopeContext,Me as summarizeResolvedAuthContext,Be as switchContextWithResolvedState,V as toAuthFailureEnvelope,f as toAuthSuccessEnvelope,A as unauthorized,kt as upsertLocalIdentityAndAssignment};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var G=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var Ee=(i,e)=>{for(var t in e)G(i,t,{get:e[t],enumerable:!0})},Ce=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Ie(e))!Re.call(i,n)&&n!==t&&G(i,n,{get:()=>e[n],enumerable:!(r=ge(e,n))||r.enumerable});return i};var we=i=>Ce(G({},"__esModule",{value:!0}),i);var Ke={};Ee(Ke,{AuthRejectionError:()=>O,DefaultAuthOfflinePolicy:()=>x,OFAUTH_CONTRACT_STAGE:()=>Ge,OFAUTH_TABLES:()=>a,OfauthCore:()=>V,OfauthCoreBuilder:()=>F,OfauthDomainError:()=>T,applyPendingMigrations:()=>Y,createContractOnlyOfauthServices:()=>He,createDbAdapterOfauthServices:()=>$,createServerAuthoritativeAuthBridge:()=>qe,evaluateProtectedRouteGate:()=>_e,getOfauthTableSchemas:()=>K,hasAnyScopeDimension:()=>be,invalidState:()=>Ue,isAssuranceLevelAtLeast:()=>b,isAuthAuditEventType:()=>xe,loginWithResolvedContext:()=>Pe,mapAuthErrorToEnvelope:()=>f,migrations:()=>X,ofauthSchema:()=>ue,refreshResolvedContext:()=>Le,switchContextWithResolvedState:()=>De,toAuthFailureEnvelope:()=>_,toAuthSuccessEnvelope:()=>m,unauthorized:()=>A,upsertLocalIdentityAndAssignment:()=>Be});module.exports=we(Ke);function be(i){return!!(i.tenantId||i.branchId||i.attributes&&Object.keys(i.attributes).length>0)}function b(i,e){let t={basic:1,elevated:2};return t[i]>=t[e]}function xe(i){return["LOGIN_SUCCESS","LOGIN_FAILED","LOCKOUT_TRIGGERED","SESSION_REVOKED","CONTEXT_SWITCHED","STEP_UP_CHALLENGED","STEP_UP_PASSED","STEP_UP_FAILED"].includes(i)}function se(i,e){if(e)return i.find(t=>t.assignmentId===e)}function Te(i,e,t){var r,n;return(n=(r=se(i,t))!=null?r:se(i,e))!=null?n:i[0]}function Oe(i,e){var t;if(e.requiredTenantId&&i.tenantId!==e.requiredTenantId||e.requiredBranchId&&i.branchId!==e.requiredBranchId)return!1;if(e.requiredScopeAttributes){let r=(t=i.attributes)!=null?t:{};for(let[n,s]of Object.entries(e.requiredScopeAttributes))if(r[n]!==s)return!1}return!0}function D(i){var e;if(i&&typeof i=="object"&&i.error&&typeof i.error.code=="string"){let t=new Error(i.error.message||i.error.code);throw t.code=i.error.code,t}return(e=i==null?void 0:i.data)!=null?e:i}async function W(i,e){var o,d,c;let t=D(await i.sessionService.getActiveSession(e.sessionId));if(!t)return null;let r=D(await i.contextService.listAssignments(e.identityId)),n=D(await i.contextService.getActiveContext(e.sessionId)),s=Te(r,n==null?void 0:n.assignmentId,e.preferredAssignmentId);return{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,assignments:r,activeContextAssignmentId:s==null?void 0:s.assignmentId,activeAssignment:s,scopeRef:(c=(d=(o=s==null?void 0:s.scopeRef)!=null?o:n==null?void 0:n.scopeRef)!=null?d:t.activeScopeRef)!=null?c:{},roleRef:s==null?void 0:s.roleRef,assuranceLevel:t.assuranceLevel}}async function Pe(i,e){let t=D(await i.identityService.login(e.principal,e.secret,e.scopeRef)),r=await W(i,{sessionId:t.sessionId,identityId:t.identity.identityId,principal:t.identity.principal});if(!r)throw new Error("session is not active after login");return r}async function Le(i,e){return W(i,e)}async function De(i,e){let t=await W(i,{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,preferredAssignmentId:e.targetAssignmentId});if(!t)throw new Error("session is not active while switching context");if(t.activeContextAssignmentId!==e.targetAssignmentId)throw new Error("requested assignment is not available for the active identity");return t}function _e(i,e={}){var r,n;if(!i)return{allowed:!1,reasonCode:"NO_SESSION"};let t=(r=e.minimumAssuranceLevel)!=null?r:"basic";return b(i.assuranceLevel,t)?(n=e.requiredRoleRefs)!=null&&n.length&&!(!!i.roleRef&&e.requiredRoleRefs.includes(i.roleRef))?{allowed:!1,reasonCode:"ROLE_FORBIDDEN"}:Oe(i.scopeRef,e)?{allowed:!0}:{allowed:!1,reasonCode:"SCOPE_FORBIDDEN"}:{allowed:!1,reasonCode:"ASSURANCE_TOO_LOW"}}var x=class{canLoginOffline(e){let t=new Date(e.nowIso).getTime(),r=new Date(e.envelope.expiresAt).getTime();return!Number.isFinite(t)||!Number.isFinite(r)?!1:t<=r}};var T=class extends Error{constructor(t,r,n=!1){super(r);this.code=t;this.retryable=n;this.name="OfauthDomainError"}},O=class extends Error{constructor(t){super(t);this.code=t;this.name="AuthRejectionError"}};function A(i,e){return new T(i,e,!1)}function Ue(i){return new T("AUTH_NOT_IMPLEMENTED",i,!1)}var ke=new Set(["AUTH_UNAUTHORIZED","AUTH_INVALID_CREDENTIAL","AUTH_LOCKED","AUTH_DISABLED"]);function Ne(i){var e;return{principal:i.principal,accessToken:i.accessToken,refreshToken:i.refreshToken,assuranceLevel:i.assuranceLevel,issuedAt:i.issuedAt,expiresAt:i.expiresAt,activeRoleRef:i.activeRoleRef,activeContext:(e=i.activeContext)!=null?e:null}}function qe(i){var n,s,o;let e=(n=i.now)!=null?n:(()=>new Date().toISOString()),t=(s=i.isOnline)!=null?s:(()=>!0),r=(o=i.offlinePolicy)!=null?o:new x;return{async login(d){var I,R;let c=String(d.principal||"").trim();if(!c)return{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"};if(t())try{let p=await i.authority.login(d),w=Ne({principal:c,accessToken:p.accessToken,refreshToken:p.refreshToken,assuranceLevel:p.session.assuranceLevel,issuedAt:p.session.issuedAt,expiresAt:p.session.expiresAt,activeRoleRef:p.activeRoleRef,activeContext:(I=p.activeContext)!=null?I:null}),L={principal:c,identityId:p.session.identityId,roleRef:(R=p.activeRoleRef)!=null?R:null,lastOnlineAuthAt:e()};return await i.cache.setCachedIdentity(L),await i.cache.setSessionEnvelope(c,w),{status:"authenticated",mode:"online",session:w}}catch(p){return p instanceof O?{status:"rejected",reasonCode:p.code}:p instanceof Error&&ke.has(p.message)?{status:"rejected",reasonCode:p.message}:{status:"rejected",reasonCode:"AUTH_AUTHORITY_UNAVAILABLE"}}let l=await i.cache.getCachedIdentity(c),y=await i.cache.getSessionEnvelope(c);return!l||!y?{status:"rejected",reasonCode:"OFFLINE_SESSION_NOT_AVAILABLE"}:r.canLoginOffline({nowIso:e(),envelope:y})?await i.verifyOfflineSecret({principal:c,secret:d.secret})?{status:"authenticated",mode:"offline",session:y}:{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"}:{status:"rejected",reasonCode:"OFFLINE_SESSION_EXPIRED"}},async logout(d){let c=await i.cache.getSessionEnvelope(d);if(c)try{await i.authority.logout({accessToken:c.accessToken,refreshToken:c.refreshToken})}catch{}}}}function S(i){return{error:{code:"AUTH_NOT_IMPLEMENTED",message:i,retryable:!1}}}function He(){return{identityService:{async verifyCredential(){return S("identityService.verifyCredential not implemented yet")},async login(i,e){return S("identityService.login not implemented yet")},async logout(){return S("identityService.logout not implemented yet")}},sessionService:{async createSession(){return S("sessionService.createSession not implemented yet")},async refreshSession(){return S("sessionService.refreshSession not implemented yet")},async revokeSession(){return S("sessionService.revokeSession not implemented yet")},async getActiveSession(){return S("sessionService.getActiveSession not implemented yet")}},contextService:{async listAssignments(){return S("contextService.listAssignments not implemented yet")},async getActiveContext(){return S("contextService.getActiveContext not implemented yet")},async switchContext(){return S("contextService.switchContext not implemented yet")}},authPolicyService:{async getPolicySnapshot(){return S("authPolicyService.getPolicySnapshot not implemented yet")},async getStepUpRequirement(){return S("authPolicyService.getStepUpRequirement not implemented yet")},async evaluateStepUp(){return S("authPolicyService.evaluateStepUp not implemented yet")},async enforceStepUp(){return S("authPolicyService.enforceStepUp not implemented yet")},async markStepUpPassed(){return S("authPolicyService.markStepUpPassed not implemented yet")}},authAuditService:{async appendEvent(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.appendEvent not implemented yet",retryable:!1}},async queryEvents(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.queryEvents not implemented yet",retryable:!1}},async listPendingReplay(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.listPendingReplay not implemented yet",retryable:!1}},async markReplayed(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.markReplayed not implemented yet",retryable:!1}}}}}function m(i,e){return{data:i,meta:{request_id:e!=null?e:null,timestamp:new Date().toISOString()}}}function _(i,e,t={}){var r;return{error:{code:i,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:(r=t.requestId)!=null?r:null,timestamp:new Date().toISOString()}}}function f(i,e="AUTH_NOT_IMPLEMENTED",t="Unhandled auth error."){var r;if(i&&typeof i=="object"){let n=i;return _((r=n.code)!=null?r:e,n.message||t,{retryable:n.retryable})}return i instanceof Error?_(e,i.message||t):_(e,t)}function oe(i){return{async verifyCredential(e){try{return m(await i.verifyCredential(e))}catch(t){return f(t)}},async login(e,t,r){try{let n=await i.login({principal:e,secret:t,verifyMethod:"password"});return m(n)}catch(n){return f(n)}},async logout(e){try{return await i.logout(e),m({sessionId:e,revoked:!0})}catch(t){return f(t)}}}}function ae(i){return{async createSession(e){try{return m(await i.createSession(e))}catch(t){return f(t)}},async refreshSession(e){try{return m(await i.refreshSession(e))}catch(t){return f(t)}},async revokeSession(e){try{return await i.revokeSession(e),m({sessionId:e.sessionId,revoked:!0})}catch(t){return f(t)}},async getActiveSession(e){try{return m(await i.getActiveSession(e))}catch(t){return f(t)}}}}function de(i){return{async listAssignments(e){try{return m(await i.listAssignments(e))}catch(t){return f(t)}},async getActiveContext(e){try{return m(await i.getActiveContext(e))}catch(t){return f(t)}},async switchContext(e){try{return m(await i.switchContext(e))}catch(t){return f(t)}}}}function ce(i){return{async getPolicySnapshot(){try{return m(await i.getPolicySnapshot())}catch(e){return f(e)}},async getStepUpRequirement(e){try{return m(await i.getStepUpRequirement(e))}catch(t){return f(t)}},async evaluateStepUp(e,t){try{return m(await i.evaluateStepUp(e,t))}catch(r){return f(r)}},async enforceStepUp(e,t){try{return await i.enforceStepUp(e,t),m({sessionId:e,actionRef:t,enforced:!0})}catch(r){return f(r)}},async markStepUpPassed(e,t){try{return m(await i.markStepUpPassed(e,t))}catch(r){return f(r)}}}}var a={identities:"ofauth_identities",assignments:"ofauth_assignments",sessions:"ofauth_sessions",policyProfiles:"ofauth_policy_profiles",policyStepups:"ofauth_policy_stepups",auditEvents:"ofauth_audit_events"},Me=[{name:a.identities,columns:[{name:"id",type:"string"},{name:"principal",type:"string",isIndexed:!0},{name:"secretHash",type:"string"},{name:"verifyMethod",type:"string",enum:["pin","password","custom"]},{name:"status",type:"string",enum:["active","disabled","locked"],isIndexed:!0},{name:"failedAttempts",type:"number"},{name:"lockoutUntil",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.assignments,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"roleRef",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.sessions,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"activeAssignmentId",type:"string",isOptional:!0,isIndexed:!0},{name:"assuranceLevel",type:"string",enum:["basic","elevated"],isIndexed:!0},{name:"issuedAt",type:"string"},{name:"expiresAt",type:"string",isIndexed:!0},{name:"revokedAt",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyProfiles,columns:[{name:"id",type:"string"},{name:"profileId",type:"string",isIndexed:!0},{name:"defaultAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"lockoutPolicyRef",type:"string"},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyStepups,columns:[{name:"id",type:"string"},{name:"actionRef",type:"string",isIndexed:!0},{name:"requiredAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"reauthWindowSeconds",type:"number",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.auditEvents,columns:[{name:"id",type:"string"},{name:"eventType",type:"string",isIndexed:!0},{name:"identityId",type:"string",isOptional:!0,isIndexed:!0},{name:"sessionId",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"result",type:"string",enum:["success","failed"],isIndexed:!0},{name:"reasonCode",type:"string",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"syncStatus",type:"string",enum:["pending","replayed"],isIndexed:!0},{name:"replayedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]}],ue={version:2,tables:Me};function K(){return ue.tables}var U=require("ofcore");var le=5,pe=900,j=480*60;function u(){return(0,U.nowIso)()}function P(i,e){return new Date(new Date(i).getTime()+e*1e3).toISOString()}function E(i){return new Date(i).getTime()<=Date.now()}function h(i){return(0,U.makeIdFactory)(i)}function me(i){return{identityId:i.id,principal:i.principal,status:i.status}}function Q(i){return{assignmentId:i.id,identityId:i.identityId,roleRef:i.roleRef,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}}}function C(i,e,t){return{sessionId:i.id,identityId:i.identityId,activeScopeRef:e?{...e.tenantId?{tenantId:e.tenantId}:{},...e.branchId?{branchId:e.branchId}:{},...e.scopeAttributes?{attributes:e.scopeAttributes}:{}}:void 0,grantedAssignments:t!==void 0?t.map(Q):void 0,assuranceLevel:i.assuranceLevel,issuedAt:i.issuedAt,expiresAt:i.expiresAt}}async function fe(i,e,t){return i?i.verifyPin(e,t):e===t}async function ye(i,e){var t,r,n,s,o,d;i.emitActivity&&await i.emitActivity({activityId:e.eventId,activityType:`ofauth.${e.eventType.toLowerCase()}`,occurredAt:e.timestamp,scopeRef:{domain:"ofauth",...(t=e.scopeRef)!=null&&t.tenantId?{tenantId:e.scopeRef.tenantId}:{},...(r=e.scopeRef)!=null&&r.branchId?{branchId:e.scopeRef.branchId}:{}},actor:e.identityId?{userId:e.identityId}:void 0,payload:{eventType:e.eventType,result:e.result,reasonCode:(n=e.reasonCode)!=null?n:null,sessionId:(s=e.sessionId)!=null?s:null,scopeAttributes:(d=(o=e.scopeRef)==null?void 0:o.attributes)!=null?d:null}})}async function v(i,e){if(!e)return null;let t=await i.get(a.assignments,e);return!t||t.deleted?null:t}function Se(){return[{profileId:"cashier_fast",defaultAssuranceLevel:"basic",lockoutPolicyRef:"default"},{profileId:"supervisor_strict",defaultAssuranceLevel:"elevated",lockoutPolicyRef:"strict"},{profileId:"member_self_service",defaultAssuranceLevel:"basic",lockoutPolicyRef:"member"}]}var k=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-audit")}async appendEvent(e){var r,n,s,o,d,c,l,y,g,I,R;let t={id:e.eventId||this.newId(),eventType:e.eventType,identityId:(r=e.identityId)!=null?r:null,sessionId:(n=e.sessionId)!=null?n:null,tenantId:(o=(s=e.scopeRef)==null?void 0:s.tenantId)!=null?o:null,branchId:(c=(d=e.scopeRef)==null?void 0:d.branchId)!=null?c:null,scopeAttributes:(y=(l=e.scopeRef)==null?void 0:l.attributes)!=null?y:null,result:e.result,reasonCode:(g=e.reasonCode)!=null?g:null,timestamp:e.timestamp,syncStatus:(I=e.syncStatus)!=null?I:"pending",replayedAt:(R=e.replayedAt)!=null?R:null,version:1,lastModified:u(),deleted:!1};await this.db.create(a.auditEvents,t),await ye(this.options,e)}async queryEvents(e){return(await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"desc"}]})).filter(r=>e.identityId?r.identityId===e.identityId:!0).filter(r=>e.sessionId?r.sessionId===e.sessionId:!0).filter(r=>{var n;return(n=e.eventTypes)!=null&&n.length?e.eventTypes.includes(r.eventType):!0}).filter(r=>e.fromTimestamp?r.timestamp>=e.fromTimestamp:!0).filter(r=>e.toTimestamp?r.timestamp<=e.toTimestamp:!0).map(r=>{var n,s,o,d,c;return{eventId:r.id,eventType:r.eventType,identityId:(n=r.identityId)!=null?n:void 0,sessionId:(s=r.sessionId)!=null?s:void 0,scopeRef:r.tenantId||r.branchId||r.scopeAttributes?{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}:void 0,result:r.result,reasonCode:(o=r.reasonCode)!=null?o:void 0,timestamp:r.timestamp,syncStatus:(d=r.syncStatus)!=null?d:"pending",replayedAt:(c=r.replayedAt)!=null?c:void 0}})}async listPendingReplay(e={}){var r;let t=await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"asc"}]});return t.filter(n=>n.syncStatus!=="replayed").slice(0,(r=e.limit)!=null?r:t.length).map(n=>{var s,o,d,c,l;return{eventId:n.id,eventType:n.eventType,identityId:(s=n.identityId)!=null?s:void 0,sessionId:(o=n.sessionId)!=null?o:void 0,scopeRef:n.tenantId||n.branchId||n.scopeAttributes?{...n.tenantId?{tenantId:n.tenantId}:{},...n.branchId?{branchId:n.branchId}:{},...n.scopeAttributes?{attributes:n.scopeAttributes}:{}}:void 0,result:n.result,reasonCode:(d=n.reasonCode)!=null?d:void 0,timestamp:n.timestamp,syncStatus:(c=n.syncStatus)!=null?c:"pending",replayedAt:(l=n.replayedAt)!=null?l:void 0}})}async markReplayed(e,t=u()){let r=0;for(let n of e){let s=await this.db.get(a.auditEvents,n);!s||s.deleted||s.syncStatus==="replayed"||(await this.db.update(a.auditEvents,n,{syncStatus:"replayed",replayedAt:t,version:s.version+1,lastModified:u()}),r+=1)}return r}};var N=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async getActiveSessionOrThrow(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||E(t.expiresAt))throw A("AUTH_SESSION_NOT_FOUND","Session not found");return t}async getPolicySnapshot(){let e=await this.db.query(a.policyProfiles,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),t=await this.db.query(a.policyStepups,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]});return{profiles:e.length>0?e.map(r=>({profileId:r.profileId,defaultAssuranceLevel:r.defaultAssuranceLevel,lockoutPolicyRef:r.lockoutPolicyRef})):Se(),stepUpRequirements:t.map(r=>{var n;return{actionRef:r.actionRef,requiredAssuranceLevel:r.requiredAssuranceLevel,reauthWindowSeconds:(n=r.reauthWindowSeconds)!=null?n:void 0}}),version:"1",updatedAt:u()}}async getStepUpRequirement(e){var r;let t=await this.db.query(a.policyStepups,{filters:{actionRef:e,deleted:!1},limit:1});return t[0]?{actionRef:t[0].actionRef,requiredAssuranceLevel:t[0].requiredAssuranceLevel,reauthWindowSeconds:(r=t[0].reauthWindowSeconds)!=null?r:void 0}:null}async evaluateStepUp(e,t){var d;let r=await this.getActiveSessionOrThrow(e),n=await this.getStepUpRequirement(t),s=(d=n==null?void 0:n.requiredAssuranceLevel)!=null?d:"basic",o=!b(r.assuranceLevel,s);return{actionRef:t,requiredAssuranceLevel:s,currentAssuranceLevel:r.assuranceLevel,requiresStepUp:o,reauthWindowSeconds:n==null?void 0:n.reauthWindowSeconds}}async enforceStepUp(e,t){let r=await this.getActiveSessionOrThrow(e),n=await this.evaluateStepUp(e,t);if(n.requiresStepUp)throw await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_CHALLENGED",identityId:r.identityId,sessionId:e,result:"failed",reasonCode:"AUTH_STEP_UP_REQUIRED",timestamp:u()}),A("AUTH_STEP_UP_REQUIRED",`Step-up required for action '${t}' (needs ${n.requiredAssuranceLevel})`)}async markStepUpPassed(e,t){var c;let r=await this.getActiveSessionOrThrow(e),n=await this.getStepUpRequirement(t),s=(c=n==null?void 0:n.requiredAssuranceLevel)!=null?c:"elevated";await this.db.update(a.sessions,e,{assuranceLevel:s,version:r.version+1,lastModified:u()}),await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_PASSED",identityId:r.identityId,sessionId:e,result:"success",reasonCode:t,timestamp:u()});let o=await this.db.get(a.sessions,e),d=o?await v(this.db,o.activeAssignmentId):null;if(!o)throw A("AUTH_SESSION_NOT_FOUND","Session not found");return C(o,d!=null?d:void 0)}};var q=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async listAssignments(e){return(await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1},sort:[{field:"lastModified",direction:"desc"}]})).map(Q)}async getActiveContext(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||!t.activeAssignmentId)return null;let r=await v(this.db,t.activeAssignmentId);return r?{sessionId:e,assignmentId:r.id,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}}:null}async switchContext(e){let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let r=null;if(e.targetAssignmentId){if(r=await v(this.db,e.targetAssignmentId),!r||r.identityId!==t.identityId)throw A("AUTH_CONTEXT_FORBIDDEN","Requested context is not assigned to this identity")}else if(e.targetTenantId){let s=await this.db.query(a.assignments,{filters:{identityId:t.identityId,tenantId:e.targetTenantId,deleted:!1},sort:[{field:"lastModified",direction:"asc"}],limit:1});if(!s[0])throw A("AUTH_CONTEXT_FORBIDDEN","No assignments found in target tenant");r=s[0]}else throw A("AUTH_CONTEXT_INVALID","Either targetAssignmentId or targetTenantId must be provided");let n=await this.db.update(a.sessions,e.sessionId,{activeAssignmentId:r.id,version:t.version+1,lastModified:u()});return await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"CONTEXT_SWITCHED",identityId:t.identityId,sessionId:e.sessionId,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}},result:"success",reasonCode:e.reasonCode,timestamp:n.lastModified}),{activeContext:{sessionId:e.sessionId,assignmentId:r.id,scopeRef:{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}},requiresStepUp:!1,reasonCode:e.reasonCode}}};var H=class{constructor(e,t,r,n,s){this.db=e;this.options=t;this.sessionService=r;this.contextService=n;this.authAuditService=s;this.newEventId=h("auth-event")}async findIdentityByPrincipal(e){var r;return(r=(await this.db.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0])!=null?r:null}async persistFailedAttempt(e){let t=e.failedAttempts+1,r=t>=le,n=r?P(u(),pe):null,s=r?"locked":e.status;return this.db.update(a.identities,e.id,{failedAttempts:t,lockoutUntil:n,status:s,version:e.version+1,lastModified:u()})}async clearFailedAttempt(e){e.failedAttempts===0&&!e.lockoutUntil&&e.status==="active"||await this.db.update(a.identities,e.id,{failedAttempts:0,lockoutUntil:null,status:"active",version:e.version+1,lastModified:u()})}async emitAudit(e){await this.authAuditService.appendEvent(e)}async verifyCredential(e){let t=await this.findIdentityByPrincipal(e.principal);if(!t)return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",result:"failed",reasonCode:"INVALID_CREDENTIAL",timestamp:u()}),{ok:!1,reasonCode:"INVALID_CREDENTIAL",retryable:!0};if(t.status==="disabled")return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_DISABLED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_DISABLED",retryable:!1};if(t.lockoutUntil&&!E(t.lockoutUntil))return await this.emitAudit({eventId:this.newEventId(),eventType:"LOCKOUT_TRIGGERED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_LOCKED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_LOCKED",retryable:!1};if(!await fe(this.options.platformAdapter,e.secret,t.secretHash)){let o=(await this.persistFailedAttempt(t)).status==="locked"?"IDENTITY_LOCKED":"INVALID_CREDENTIAL";return await this.emitAudit({eventId:this.newEventId(),eventType:o==="IDENTITY_LOCKED"?"LOCKOUT_TRIGGERED":"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:o,timestamp:u()}),{ok:!1,reasonCode:o,retryable:o==="INVALID_CREDENTIAL"}}await this.clearFailedAttempt(t);let n=await this.contextService.listAssignments(t.id);return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_SUCCESS",identityId:t.id,scopeRef:e.scopeRef,result:"success",timestamp:u()}),{ok:!0,identity:me(t),assignments:n}}async login(e){let t=await this.verifyCredential({principal:e.principal,secret:e.secret,verifyMethod:e.verifyMethod});if(!t.ok)throw A("AUTH_INVALID_CREDENTIAL",`Authentication failed: ${t.reasonCode}`);let r=[...t.assignments].sort((s,o)=>s.assignmentId.localeCompare(o.assignmentId))[0],n=await this.sessionService.createSession({identityId:t.identity.identityId,assignmentId:r==null?void 0:r.assignmentId,assuranceLevel:"basic"});return{identity:t.identity,sessionId:n.sessionId}}async logout(e){await this.sessionService.revokeSession({sessionId:e,reasonCode:"LOGOUT"}),await this.emitAudit({eventId:this.newEventId(),eventType:"SESSION_REVOKED",sessionId:e,result:"success",reasonCode:"LOGOUT",timestamp:u()})}};var M=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-session")}async resolveGrantedAssignments(e,t){let r=await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1}});return t!=null&&t.tenantId?r.filter(n=>n.tenantId===t.tenantId):r}async createSession(e){var d,c,l,y;let t=u(),r=P(t,(d=e.ttlSeconds)!=null?d:j),n=await this.db.create(a.sessions,{id:this.newId(),identityId:e.identityId,activeAssignmentId:(c=e.assignmentId)!=null?c:null,assuranceLevel:(l=e.assuranceLevel)!=null?l:"basic",issuedAt:t,expiresAt:r,revokedAt:null,version:1,lastModified:t,deleted:!1}),s=await v(this.db,n.activeAssignmentId),o=await this.resolveGrantedAssignments(n.identityId,s);return(y=this.options.logger)==null||y.logInfo("[ofauth] session created",{sessionId:n.id,identityId:n.identityId}),C(n,s,o)}async refreshSession(e){var o;let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let r=await this.db.update(a.sessions,e.sessionId,{expiresAt:P(u(),(o=e.ttlSeconds)!=null?o:j),version:t.version+1,lastModified:u()}),n=await v(this.db,r.activeAssignmentId),s=await this.resolveGrantedAssignments(r.identityId,n);return C(r,n,s)}async revokeSession(e){var r,n;let t=await this.db.get(a.sessions,e.sessionId);!t||t.deleted||t.revokedAt||(await this.db.update(a.sessions,e.sessionId,{revokedAt:u(),version:t.version+1,lastModified:u()}),(n=this.options.logger)==null||n.logInfo("[ofauth] session revoked",{sessionId:e.sessionId,reasonCode:(r=e.reasonCode)!=null?r:null}))}async getActiveSession(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||E(t.expiresAt))return null;let r=await v(this.db,t.activeAssignmentId),n=await this.resolveGrantedAssignments(t.identityId,r);return C(t,r,n)}};async function $(i,e={}){let t=new k(i,e),r=new M(i,e),n=new q(i,t),s=new N(i,t),o=new H(i,e,r,n,t);return{identityService:oe(o),sessionService:ae(r),contextService:de(n),authPolicyService:ce(s),authAuditService:t}}function Ve(){return new Date().toISOString()}function Ae(i){return`${i}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}async function Fe(i,e){return i!=null&&i.hashPin?i.hashPin(e):`sha256:${e}`}async function Be(i){var I,R,p,w,L,J,Z,ee,te,ie,re,ne;let e=i.principal.trim();if(!e)throw new Error("AUTH_PROVISION_PRINCIPAL_REQUIRED");if(!((I=i.roleRef)!=null&&I.trim()))throw new Error("AUTH_PROVISION_ROLE_REQUIRED");let t=Ve(),r=await Fe(i.platformAdapter,i.secret),n=i.dbAdapter,o=(await n.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0],d=(R=o==null?void 0:o.id)!=null?R:Ae("ofauth-identity");o?await n.update(a.identities,d,{secretHash:r,status:"active",lastModified:t}):await n.create(a.identities,{id:d,principal:e,secretHash:r,verifyMethod:"pin",status:"active",failedAttempts:0,lockoutUntil:null,version:1,lastModified:t,deleted:!1});let l=(await n.query(a.assignments,{filters:{identityId:d,deleted:!1},limit:1}))[0],y=(p=l==null?void 0:l.id)!=null?p:Ae("ofauth-assignment"),g={source:(w=i.source)!=null?w:"host-app"};return l?await n.update(a.assignments,y,{roleRef:i.roleRef,tenantId:(J=(L=i.scope)==null?void 0:L.tenantId)!=null?J:null,branchId:(ee=(Z=i.scope)==null?void 0:Z.branchId)!=null?ee:null,scopeAttributes:g,lastModified:t}):await n.create(a.assignments,{id:y,identityId:d,roleRef:i.roleRef,tenantId:(ie=(te=i.scope)==null?void 0:te.tenantId)!=null?ie:null,branchId:(ne=(re=i.scope)==null?void 0:re.branchId)!=null?ne:null,scopeAttributes:g,version:1,lastModified:t,deleted:!1}),{identityId:d,assignmentId:y}}var Ge="phase2-runtime-logic";var ve=require("ofcore"),z=require("ofcore"),B=require("ofcore");var X=[{toVersion:1,up:async i=>{let e=K();for(let t of e)try{await i.addTable(t)}catch{}}}];var We={logInfo(){},logWarn(){},logError(){}};async function Y(i,e=We){e.logInfo("[ofauth] starting database migration process");let t=[...X].sort((s,o)=>s.toVersion-o.toVersion),r=t.length>0?t[t.length-1].toVersion:0,n=await i.getSchemaVersion();if((n==null||n<0)&&(n=0),n>=r){e.logInfo(`[ofauth] database already up-to-date at v${n}`);return}for(let s of t)s.toVersion>n&&(e.logInfo(`[ofauth] applying migration v${s.toVersion}`),await s.up(i),await i.setSchemaVersion(s.toVersion),n=s.toVersion);e.logInfo(`[ofauth] migration completed at v${n}`)}var V=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=(0,B.asReadonlyStore)(this.runtimeStateStore)}static builder(){return new F}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.start(e),this.domainServices=he(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async init(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.init(e),this.domainServices=he(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async stop(){this.runtimeStateStore.setState({phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState({phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()}),e}}isStarted(){return this.runtime.isStarted()}};function he(i){if(!i)throw new Error("Ofauth runtime started without domain services");return i}var F=class{constructor(){this.runtimeBuilder=ve.CoreRuntime.builder();this.domainServiceOverrides={};this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new z.InMemoryDbAdapter)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}overrideDomainServices(e){return this.domainServiceOverrides={...this.domainServiceOverrides,...e},this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}withMigrationRunner(e){return this.withRuntimeHooks({runMigrations:e})}build(){var n;let e=(0,B.createStore)({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t=async s=>{var d,c;let o=(d=s.registry)==null?void 0:d.dbAdapter;o&&await Y(o,(c=s.registry)==null?void 0:c.loggerAdapter)};this.runtimeBuilder.withHooks({...this.runtimeHooks,runMigrations:(n=this.runtimeHooks.runMigrations)!=null?n:t,createDomainServices:async s=>{var d,c,l,y;return{...this.domainServicesFactory?await this.domainServicesFactory():await $((c=(d=s.registry)==null?void 0:d.dbAdapter)!=null?c:new z.InMemoryDbAdapter,{logger:(l=s.registry)==null?void 0:l.loggerAdapter,platformAdapter:(y=s.registry)==null?void 0:y.platformAdapter,emitActivity:async g=>{await s.emitActivity(g)}}),...this.domainServiceOverrides}}});let r=this.runtimeBuilder.build();return new V(r,e)}};
|
|
1
|
+
"use strict";var G=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var be=(n,e)=>{for(var t in e)G(n,t,{get:e[t],enumerable:!0})},xe=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ee(e))!we.call(n,r)&&r!==t&&G(n,r,{get:()=>e[r],enumerable:!(i=Ce(e,r))||i.enumerable});return n};var Te=n=>xe(G({},"__esModule",{value:!0}),n);var Xe={};be(Xe,{AuthRejectionError:()=>O,DefaultAuthOfflinePolicy:()=>x,OFAUTH_CONTRACT_STAGE:()=>Qe,OFAUTH_TABLES:()=>a,OfauthCore:()=>V,OfauthCoreBuilder:()=>F,OfauthDomainError:()=>T,applyPendingMigrations:()=>J,createContractOnlyOfauthServices:()=>Ge,createDbAdapterOfauthServices:()=>X,createServerAuthoritativeAuthBridge:()=>Be,evaluateProtectedRouteGate:()=>He,formatAuthContextSummary:()=>_e,getOfauthTableSchemas:()=>K,hasAnyScopeDimension:()=>Oe,invalidState:()=>Me,isAssuranceLevelAtLeast:()=>b,isAuthAuditEventType:()=>Pe,loginWithResolvedContext:()=>ke,mapAuthErrorToEnvelope:()=>f,migrations:()=>Y,ofauthSchema:()=>me,refreshResolvedContext:()=>Ne,summarizeAuthScopeContext:()=>de,summarizeResolvedAuthContext:()=>Ue,switchContextWithResolvedState:()=>qe,toAuthFailureEnvelope:()=>_,toAuthSuccessEnvelope:()=>m,unauthorized:()=>A,upsertLocalIdentityAndAssignment:()=>$e});module.exports=Te(Xe);function Oe(n){return!!(n.tenantId||n.branchId||n.attributes&&Object.keys(n.attributes).length>0)}function b(n,e){let t={basic:1,elevated:2};return t[n]>=t[e]}function Pe(n){return["LOGIN_SUCCESS","LOGIN_FAILED","LOCKOUT_TRIGGERED","SESSION_REVOKED","CONTEXT_SWITCHED","STEP_UP_CHALLENGED","STEP_UP_PASSED","STEP_UP_FAILED"].includes(n)}function ae(n,e){if(e)return n.find(t=>t.assignmentId===e)}function Le(n,e,t){var i,r;return(r=(i=ae(n,t))!=null?i:ae(n,e))!=null?r:n[0]}function De(n,e){var t;if(e.requiredTenantId&&n.tenantId!==e.requiredTenantId||e.requiredBranchId&&n.branchId!==e.requiredBranchId)return!1;if(e.requiredScopeAttributes){let i=(t=n.attributes)!=null?t:{};for(let[r,s]of Object.entries(e.requiredScopeAttributes))if(i[r]!==s)return!1}return!0}function W(n){if(typeof n!="string")return null;let e=n.trim();return e.length>0?e:null}function D(n){var e;if(n&&typeof n=="object"&&n.error&&typeof n.error.code=="string"){let t=new Error(n.error.message||n.error.code);throw t.code=n.error.code,t}return(e=n==null?void 0:n.data)!=null?e:n}async function j(n,e){var o,d,c;let t=D(await n.sessionService.getActiveSession(e.sessionId));if(!t)return null;let i=D(await n.contextService.listAssignments(e.identityId)),r=D(await n.contextService.getActiveContext(e.sessionId)),s=Le(i,r==null?void 0:r.assignmentId,e.preferredAssignmentId);return{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,assignments:i,activeContextAssignmentId:s==null?void 0:s.assignmentId,activeAssignment:s,scopeRef:(c=(d=(o=s==null?void 0:s.scopeRef)!=null?o:r==null?void 0:r.scopeRef)!=null?d:t.activeScopeRef)!=null?c:{},roleRef:s==null?void 0:s.roleRef,assuranceLevel:t.assuranceLevel}}function de(n){var e,t,i,r,s,o,d;return{assignmentStatus:n.assignmentId?"assigned":"unassigned",activeAssignmentId:(e=n.assignmentId)!=null?e:null,activeRoleRef:(t=n.roleRef)!=null?t:null,activeTenantId:W((i=n.scopeRef)==null?void 0:i.tenantId),activeBranchId:W((r=n.scopeRef)==null?void 0:r.branchId),activeDomainId:W((o=(s=n.scopeRef)==null?void 0:s.attributes)==null?void 0:o.domainId),assuranceLevel:(d=n.assuranceLevel)!=null?d:null}}function _e(n){var e,t,i,r,s;return n?[`assignment=${(e=n.activeAssignmentId)!=null?e:n.assignmentStatus}`,`tenant=${(t=n.activeTenantId)!=null?t:"-"}`,`branch=${(i=n.activeBranchId)!=null?i:"-"}`,`domain=${(r=n.activeDomainId)!=null?r:"-"}`,`assurance=${(s=n.assuranceLevel)!=null?s:"-"}`].join(" | "):"assignment=unassigned | tenant=- | branch=- | domain=- | assurance=-"}function Ue(n){var e;return n?de({scopeRef:n.scopeRef,roleRef:n.roleRef,assuranceLevel:n.assuranceLevel,assignmentId:(e=n.activeContextAssignmentId)!=null?e:null}):null}async function ke(n,e){let t=D(await n.identityService.login(e.principal,e.secret,e.scopeRef)),i=await j(n,{sessionId:t.sessionId,identityId:t.identity.identityId,principal:t.identity.principal});if(!i)throw new Error("session is not active after login");return i}async function Ne(n,e){return j(n,e)}async function qe(n,e){let t=await j(n,{sessionId:e.sessionId,identityId:e.identityId,principal:e.principal,preferredAssignmentId:e.targetAssignmentId});if(!t)throw new Error("session is not active while switching context");if(t.activeContextAssignmentId!==e.targetAssignmentId)throw new Error("requested assignment is not available for the active identity");return t}function He(n,e={}){var i,r;if(!n)return{allowed:!1,reasonCode:"NO_SESSION"};let t=(i=e.minimumAssuranceLevel)!=null?i:"basic";return b(n.assuranceLevel,t)?(r=e.requiredRoleRefs)!=null&&r.length&&!(!!n.roleRef&&e.requiredRoleRefs.includes(n.roleRef))?{allowed:!1,reasonCode:"ROLE_FORBIDDEN"}:De(n.scopeRef,e)?{allowed:!0}:{allowed:!1,reasonCode:"SCOPE_FORBIDDEN"}:{allowed:!1,reasonCode:"ASSURANCE_TOO_LOW"}}var x=class{canLoginOffline(e){let t=new Date(e.nowIso).getTime(),i=new Date(e.envelope.expiresAt).getTime();return!Number.isFinite(t)||!Number.isFinite(i)?!1:t<=i}};var T=class extends Error{constructor(t,i,r=!1){super(i);this.code=t;this.retryable=r;this.name="OfauthDomainError"}},O=class extends Error{constructor(t){super(t);this.code=t;this.name="AuthRejectionError"}};function A(n,e){return new T(n,e,!1)}function Me(n){return new T("AUTH_NOT_IMPLEMENTED",n,!1)}var Ve=new Set(["AUTH_UNAUTHORIZED","AUTH_INVALID_CREDENTIAL","AUTH_LOCKED","AUTH_DISABLED"]);function Fe(n){var e;return{principal:n.principal,accessToken:n.accessToken,refreshToken:n.refreshToken,assuranceLevel:n.assuranceLevel,issuedAt:n.issuedAt,expiresAt:n.expiresAt,activeRoleRef:n.activeRoleRef,activeContext:(e=n.activeContext)!=null?e:null}}function Be(n){var r,s,o;let e=(r=n.now)!=null?r:(()=>new Date().toISOString()),t=(s=n.isOnline)!=null?s:(()=>!0),i=(o=n.offlinePolicy)!=null?o:new x;return{async login(d){var I,R;let c=String(d.principal||"").trim();if(!c)return{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"};if(t())try{let p=await n.authority.login(d),w=Fe({principal:c,accessToken:p.accessToken,refreshToken:p.refreshToken,assuranceLevel:p.session.assuranceLevel,issuedAt:p.session.issuedAt,expiresAt:p.session.expiresAt,activeRoleRef:p.activeRoleRef,activeContext:(I=p.activeContext)!=null?I:null}),L={principal:c,identityId:p.session.identityId,roleRef:(R=p.activeRoleRef)!=null?R:null,lastOnlineAuthAt:e()};return await n.cache.setCachedIdentity(L),await n.cache.setSessionEnvelope(c,w),{status:"authenticated",mode:"online",session:w}}catch(p){return p instanceof O?{status:"rejected",reasonCode:p.code}:p instanceof Error&&Ve.has(p.message)?{status:"rejected",reasonCode:p.message}:{status:"rejected",reasonCode:"AUTH_AUTHORITY_UNAVAILABLE"}}let l=await n.cache.getCachedIdentity(c),y=await n.cache.getSessionEnvelope(c);return!l||!y?{status:"rejected",reasonCode:"OFFLINE_SESSION_NOT_AVAILABLE"}:i.canLoginOffline({nowIso:e(),envelope:y})?await n.verifyOfflineSecret({principal:c,secret:d.secret})?{status:"authenticated",mode:"offline",session:y}:{status:"rejected",reasonCode:"AUTH_INVALID_CREDENTIAL"}:{status:"rejected",reasonCode:"OFFLINE_SESSION_EXPIRED"}},async logout(d){let c=await n.cache.getSessionEnvelope(d);if(c)try{await n.authority.logout({accessToken:c.accessToken,refreshToken:c.refreshToken})}catch{}}}}function S(n){return{error:{code:"AUTH_NOT_IMPLEMENTED",message:n,retryable:!1}}}function Ge(){return{identityService:{async verifyCredential(){return S("identityService.verifyCredential not implemented yet")},async login(n,e){return S("identityService.login not implemented yet")},async logout(){return S("identityService.logout not implemented yet")}},sessionService:{async createSession(){return S("sessionService.createSession not implemented yet")},async refreshSession(){return S("sessionService.refreshSession not implemented yet")},async revokeSession(){return S("sessionService.revokeSession not implemented yet")},async getActiveSession(){return S("sessionService.getActiveSession not implemented yet")}},contextService:{async listAssignments(){return S("contextService.listAssignments not implemented yet")},async getActiveContext(){return S("contextService.getActiveContext not implemented yet")},async switchContext(){return S("contextService.switchContext not implemented yet")}},authPolicyService:{async getPolicySnapshot(){return S("authPolicyService.getPolicySnapshot not implemented yet")},async getStepUpRequirement(){return S("authPolicyService.getStepUpRequirement not implemented yet")},async evaluateStepUp(){return S("authPolicyService.evaluateStepUp not implemented yet")},async enforceStepUp(){return S("authPolicyService.enforceStepUp not implemented yet")},async markStepUpPassed(){return S("authPolicyService.markStepUpPassed not implemented yet")}},authAuditService:{async appendEvent(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.appendEvent not implemented yet",retryable:!1}},async queryEvents(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.queryEvents not implemented yet",retryable:!1}},async listPendingReplay(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.listPendingReplay not implemented yet",retryable:!1}},async markReplayed(){throw{code:"AUTH_NOT_IMPLEMENTED",message:"authAuditService.markReplayed not implemented yet",retryable:!1}}}}}function m(n,e){return{data:n,meta:{request_id:e!=null?e:null,timestamp:new Date().toISOString()}}}function _(n,e,t={}){var i;return{error:{code:n,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:(i=t.requestId)!=null?i:null,timestamp:new Date().toISOString()}}}function f(n,e="AUTH_NOT_IMPLEMENTED",t="Unhandled auth error."){var i;if(n&&typeof n=="object"){let r=n;return _((i=r.code)!=null?i:e,r.message||t,{retryable:r.retryable})}return n instanceof Error?_(e,n.message||t):_(e,t)}function ce(n){return{async verifyCredential(e){try{return m(await n.verifyCredential(e))}catch(t){return f(t)}},async login(e,t,i){try{let r=await n.login({principal:e,secret:t,verifyMethod:"password"});return m(r)}catch(r){return f(r)}},async logout(e){try{return await n.logout(e),m({sessionId:e,revoked:!0})}catch(t){return f(t)}}}}function ue(n){return{async createSession(e){try{return m(await n.createSession(e))}catch(t){return f(t)}},async refreshSession(e){try{return m(await n.refreshSession(e))}catch(t){return f(t)}},async revokeSession(e){try{return await n.revokeSession(e),m({sessionId:e.sessionId,revoked:!0})}catch(t){return f(t)}},async getActiveSession(e){try{return m(await n.getActiveSession(e))}catch(t){return f(t)}}}}function le(n){return{async listAssignments(e){try{return m(await n.listAssignments(e))}catch(t){return f(t)}},async getActiveContext(e){try{return m(await n.getActiveContext(e))}catch(t){return f(t)}},async switchContext(e){try{return m(await n.switchContext(e))}catch(t){return f(t)}}}}function pe(n){return{async getPolicySnapshot(){try{return m(await n.getPolicySnapshot())}catch(e){return f(e)}},async getStepUpRequirement(e){try{return m(await n.getStepUpRequirement(e))}catch(t){return f(t)}},async evaluateStepUp(e,t){try{return m(await n.evaluateStepUp(e,t))}catch(i){return f(i)}},async enforceStepUp(e,t){try{return await n.enforceStepUp(e,t),m({sessionId:e,actionRef:t,enforced:!0})}catch(i){return f(i)}},async markStepUpPassed(e,t){try{return m(await n.markStepUpPassed(e,t))}catch(i){return f(i)}}}}var a={identities:"ofauth_identities",assignments:"ofauth_assignments",sessions:"ofauth_sessions",policyProfiles:"ofauth_policy_profiles",policyStepups:"ofauth_policy_stepups",auditEvents:"ofauth_audit_events"},We=[{name:a.identities,columns:[{name:"id",type:"string"},{name:"principal",type:"string",isIndexed:!0},{name:"secretHash",type:"string"},{name:"verifyMethod",type:"string",enum:["pin","password","custom"]},{name:"status",type:"string",enum:["active","disabled","locked"],isIndexed:!0},{name:"failedAttempts",type:"number"},{name:"lockoutUntil",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.assignments,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"roleRef",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.sessions,columns:[{name:"id",type:"string"},{name:"identityId",type:"string",isIndexed:!0},{name:"activeAssignmentId",type:"string",isOptional:!0,isIndexed:!0},{name:"assuranceLevel",type:"string",enum:["basic","elevated"],isIndexed:!0},{name:"issuedAt",type:"string"},{name:"expiresAt",type:"string",isIndexed:!0},{name:"revokedAt",type:"string",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyProfiles,columns:[{name:"id",type:"string"},{name:"profileId",type:"string",isIndexed:!0},{name:"defaultAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"lockoutPolicyRef",type:"string"},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.policyStepups,columns:[{name:"id",type:"string"},{name:"actionRef",type:"string",isIndexed:!0},{name:"requiredAssuranceLevel",type:"string",enum:["basic","elevated"]},{name:"reauthWindowSeconds",type:"number",isOptional:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:a.auditEvents,columns:[{name:"id",type:"string"},{name:"eventType",type:"string",isIndexed:!0},{name:"identityId",type:"string",isOptional:!0,isIndexed:!0},{name:"sessionId",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"scopeAttributes",type:"json",isOptional:!0},{name:"result",type:"string",enum:["success","failed"],isIndexed:!0},{name:"reasonCode",type:"string",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"syncStatus",type:"string",enum:["pending","replayed"],isIndexed:!0},{name:"replayedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"version",type:"number"},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]}],me={version:2,tables:We};function K(){return me.tables}var U=require("ofcore");var fe=5,ye=900,$=480*60;function u(){return(0,U.nowIso)()}function P(n,e){return new Date(new Date(n).getTime()+e*1e3).toISOString()}function C(n){return new Date(n).getTime()<=Date.now()}function h(n){return(0,U.makeIdFactory)(n)}function Se(n){return{identityId:n.id,principal:n.principal,status:n.status}}function Q(n){return{assignmentId:n.id,identityId:n.identityId,roleRef:n.roleRef,scopeRef:{...n.tenantId?{tenantId:n.tenantId}:{},...n.branchId?{branchId:n.branchId}:{},...n.scopeAttributes?{attributes:n.scopeAttributes}:{}}}}function E(n,e,t){return{sessionId:n.id,identityId:n.identityId,activeScopeRef:e?{...e.tenantId?{tenantId:e.tenantId}:{},...e.branchId?{branchId:e.branchId}:{},...e.scopeAttributes?{attributes:e.scopeAttributes}:{}}:void 0,grantedAssignments:t!==void 0?t.map(Q):void 0,assuranceLevel:n.assuranceLevel,issuedAt:n.issuedAt,expiresAt:n.expiresAt}}async function Ae(n,e,t){return n?n.verifyPin(e,t):e===t}async function he(n,e){var t,i,r,s,o,d;n.emitActivity&&await n.emitActivity({activityId:e.eventId,activityType:`ofauth.${e.eventType.toLowerCase()}`,occurredAt:e.timestamp,scopeRef:{domain:"ofauth",...(t=e.scopeRef)!=null&&t.tenantId?{tenantId:e.scopeRef.tenantId}:{},...(i=e.scopeRef)!=null&&i.branchId?{branchId:e.scopeRef.branchId}:{}},actor:e.identityId?{userId:e.identityId}:void 0,payload:{eventType:e.eventType,result:e.result,reasonCode:(r=e.reasonCode)!=null?r:null,sessionId:(s=e.sessionId)!=null?s:null,scopeAttributes:(d=(o=e.scopeRef)==null?void 0:o.attributes)!=null?d:null}})}async function v(n,e){if(!e)return null;let t=await n.get(a.assignments,e);return!t||t.deleted?null:t}function ve(){return[{profileId:"cashier_fast",defaultAssuranceLevel:"basic",lockoutPolicyRef:"default"},{profileId:"supervisor_strict",defaultAssuranceLevel:"elevated",lockoutPolicyRef:"strict"},{profileId:"member_self_service",defaultAssuranceLevel:"basic",lockoutPolicyRef:"member"}]}function z(){return[{actionRef:"auth.device_identity_revoke",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300},{actionRef:"auth.device_identity_reissue",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300},{actionRef:"auth.assignment_revoke",requiredAssuranceLevel:"elevated",reauthWindowSeconds:300}]}var k=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-audit")}async appendEvent(e){var i,r,s,o,d,c,l,y,g,I,R;let t={id:e.eventId||this.newId(),eventType:e.eventType,identityId:(i=e.identityId)!=null?i:null,sessionId:(r=e.sessionId)!=null?r:null,tenantId:(o=(s=e.scopeRef)==null?void 0:s.tenantId)!=null?o:null,branchId:(c=(d=e.scopeRef)==null?void 0:d.branchId)!=null?c:null,scopeAttributes:(y=(l=e.scopeRef)==null?void 0:l.attributes)!=null?y:null,result:e.result,reasonCode:(g=e.reasonCode)!=null?g:null,timestamp:e.timestamp,syncStatus:(I=e.syncStatus)!=null?I:"pending",replayedAt:(R=e.replayedAt)!=null?R:null,version:1,lastModified:u(),deleted:!1};await this.db.create(a.auditEvents,t),await he(this.options,e)}async queryEvents(e){return(await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"desc"}]})).filter(i=>e.identityId?i.identityId===e.identityId:!0).filter(i=>e.sessionId?i.sessionId===e.sessionId:!0).filter(i=>{var r;return(r=e.eventTypes)!=null&&r.length?e.eventTypes.includes(i.eventType):!0}).filter(i=>e.fromTimestamp?i.timestamp>=e.fromTimestamp:!0).filter(i=>e.toTimestamp?i.timestamp<=e.toTimestamp:!0).map(i=>{var r,s,o,d,c;return{eventId:i.id,eventType:i.eventType,identityId:(r=i.identityId)!=null?r:void 0,sessionId:(s=i.sessionId)!=null?s:void 0,scopeRef:i.tenantId||i.branchId||i.scopeAttributes?{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}:void 0,result:i.result,reasonCode:(o=i.reasonCode)!=null?o:void 0,timestamp:i.timestamp,syncStatus:(d=i.syncStatus)!=null?d:"pending",replayedAt:(c=i.replayedAt)!=null?c:void 0}})}async listPendingReplay(e={}){var i;let t=await this.db.query(a.auditEvents,{filters:{deleted:!1},sort:[{field:"timestamp",direction:"asc"}]});return t.filter(r=>r.syncStatus!=="replayed").slice(0,(i=e.limit)!=null?i:t.length).map(r=>{var s,o,d,c,l;return{eventId:r.id,eventType:r.eventType,identityId:(s=r.identityId)!=null?s:void 0,sessionId:(o=r.sessionId)!=null?o:void 0,scopeRef:r.tenantId||r.branchId||r.scopeAttributes?{...r.tenantId?{tenantId:r.tenantId}:{},...r.branchId?{branchId:r.branchId}:{},...r.scopeAttributes?{attributes:r.scopeAttributes}:{}}:void 0,result:r.result,reasonCode:(d=r.reasonCode)!=null?d:void 0,timestamp:r.timestamp,syncStatus:(c=r.syncStatus)!=null?c:"pending",replayedAt:(l=r.replayedAt)!=null?l:void 0}})}async markReplayed(e,t=u()){let i=0;for(let r of e){let s=await this.db.get(a.auditEvents,r);!s||s.deleted||s.syncStatus==="replayed"||(await this.db.update(a.auditEvents,r,{syncStatus:"replayed",replayedAt:t,version:s.version+1,lastModified:u()}),i+=1)}return i}};var N=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async getActiveSessionOrThrow(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||C(t.expiresAt))throw A("AUTH_SESSION_NOT_FOUND","Session not found");return t}async getPolicySnapshot(){var s;let e=await this.db.query(a.policyProfiles,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),t=await this.db.query(a.policyStepups,{filters:{deleted:!1},sort:[{field:"lastModified",direction:"desc"}]}),i=z(),r=new Map(i.map(o=>[o.actionRef,o]));for(let o of t)r.set(o.actionRef,{actionRef:o.actionRef,requiredAssuranceLevel:o.requiredAssuranceLevel,reauthWindowSeconds:(s=o.reauthWindowSeconds)!=null?s:void 0});return{profiles:e.length>0?e.map(o=>({profileId:o.profileId,defaultAssuranceLevel:o.defaultAssuranceLevel,lockoutPolicyRef:o.lockoutPolicyRef})):ve(),stepUpRequirements:Array.from(r.values()),version:"1",updatedAt:u()}}async getStepUpRequirement(e){var i,r;let t=await this.db.query(a.policyStepups,{filters:{actionRef:e,deleted:!1},limit:1});return t[0]?{actionRef:t[0].actionRef,requiredAssuranceLevel:t[0].requiredAssuranceLevel,reauthWindowSeconds:(r=t[0].reauthWindowSeconds)!=null?r:void 0}:(i=z().find(s=>s.actionRef===e))!=null?i:null}async evaluateStepUp(e,t){var d;let i=await this.getActiveSessionOrThrow(e),r=await this.getStepUpRequirement(t),s=(d=r==null?void 0:r.requiredAssuranceLevel)!=null?d:"basic",o=!b(i.assuranceLevel,s);return{actionRef:t,requiredAssuranceLevel:s,currentAssuranceLevel:i.assuranceLevel,requiresStepUp:o,reauthWindowSeconds:r==null?void 0:r.reauthWindowSeconds}}async enforceStepUp(e,t){let i=await this.getActiveSessionOrThrow(e),r=await this.evaluateStepUp(e,t);if(r.requiresStepUp)throw await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_CHALLENGED",identityId:i.identityId,sessionId:e,result:"failed",reasonCode:"AUTH_STEP_UP_REQUIRED",timestamp:u()}),A("AUTH_STEP_UP_REQUIRED",`Step-up required for action '${t}' (needs ${r.requiredAssuranceLevel})`)}async markStepUpPassed(e,t){var c;let i=await this.getActiveSessionOrThrow(e),r=await this.getStepUpRequirement(t),s=(c=r==null?void 0:r.requiredAssuranceLevel)!=null?c:"elevated";await this.db.update(a.sessions,e,{assuranceLevel:s,version:i.version+1,lastModified:u()}),await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"STEP_UP_PASSED",identityId:i.identityId,sessionId:e,result:"success",reasonCode:t,timestamp:u()});let o=await this.db.get(a.sessions,e),d=o?await v(this.db,o.activeAssignmentId):null;if(!o)throw A("AUTH_SESSION_NOT_FOUND","Session not found");return E(o,d!=null?d:void 0)}};var q=class{constructor(e,t){this.db=e;this.authAuditService=t;this.newEventId=h("auth-event")}async listAssignments(e){return(await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1},sort:[{field:"lastModified",direction:"desc"}]})).map(Q)}async getActiveContext(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||!t.activeAssignmentId)return null;let i=await v(this.db,t.activeAssignmentId);return i?{sessionId:e,assignmentId:i.id,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}}:null}async switchContext(e){let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let i=null;if(e.targetAssignmentId){if(i=await v(this.db,e.targetAssignmentId),!i||i.identityId!==t.identityId)throw A("AUTH_CONTEXT_FORBIDDEN","Requested context is not assigned to this identity")}else if(e.targetTenantId){let s=await this.db.query(a.assignments,{filters:{identityId:t.identityId,tenantId:e.targetTenantId,deleted:!1},sort:[{field:"lastModified",direction:"asc"}],limit:1});if(!s[0])throw A("AUTH_CONTEXT_FORBIDDEN","No assignments found in target tenant");i=s[0]}else throw A("AUTH_CONTEXT_INVALID","Either targetAssignmentId or targetTenantId must be provided");let r=await this.db.update(a.sessions,e.sessionId,{activeAssignmentId:i.id,version:t.version+1,lastModified:u()});return await this.authAuditService.appendEvent({eventId:this.newEventId(),eventType:"CONTEXT_SWITCHED",identityId:t.identityId,sessionId:e.sessionId,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}},result:"success",reasonCode:e.reasonCode,timestamp:r.lastModified}),{activeContext:{sessionId:e.sessionId,assignmentId:i.id,scopeRef:{...i.tenantId?{tenantId:i.tenantId}:{},...i.branchId?{branchId:i.branchId}:{},...i.scopeAttributes?{attributes:i.scopeAttributes}:{}}},requiresStepUp:!1,reasonCode:e.reasonCode}}};var H=class{constructor(e,t,i,r,s){this.db=e;this.options=t;this.sessionService=i;this.contextService=r;this.authAuditService=s;this.newEventId=h("auth-event")}async findIdentityByPrincipal(e){var i;return(i=(await this.db.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0])!=null?i:null}async persistFailedAttempt(e){let t=e.failedAttempts+1,i=t>=fe,r=i?P(u(),ye):null,s=i?"locked":e.status;return this.db.update(a.identities,e.id,{failedAttempts:t,lockoutUntil:r,status:s,version:e.version+1,lastModified:u()})}async clearFailedAttempt(e){e.failedAttempts===0&&!e.lockoutUntil&&e.status==="active"||await this.db.update(a.identities,e.id,{failedAttempts:0,lockoutUntil:null,status:"active",version:e.version+1,lastModified:u()})}async emitAudit(e){await this.authAuditService.appendEvent(e)}async verifyCredential(e){let t=await this.findIdentityByPrincipal(e.principal);if(!t)return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",result:"failed",reasonCode:"INVALID_CREDENTIAL",timestamp:u()}),{ok:!1,reasonCode:"INVALID_CREDENTIAL",retryable:!0};if(t.status==="disabled")return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_DISABLED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_DISABLED",retryable:!1};if(t.lockoutUntil&&!C(t.lockoutUntil))return await this.emitAudit({eventId:this.newEventId(),eventType:"LOCKOUT_TRIGGERED",identityId:t.id,result:"failed",reasonCode:"IDENTITY_LOCKED",timestamp:u()}),{ok:!1,reasonCode:"IDENTITY_LOCKED",retryable:!1};if(!await Ae(this.options.platformAdapter,e.secret,t.secretHash)){let o=(await this.persistFailedAttempt(t)).status==="locked"?"IDENTITY_LOCKED":"INVALID_CREDENTIAL";return await this.emitAudit({eventId:this.newEventId(),eventType:o==="IDENTITY_LOCKED"?"LOCKOUT_TRIGGERED":"LOGIN_FAILED",identityId:t.id,result:"failed",reasonCode:o,timestamp:u()}),{ok:!1,reasonCode:o,retryable:o==="INVALID_CREDENTIAL"}}await this.clearFailedAttempt(t);let r=await this.contextService.listAssignments(t.id);return await this.emitAudit({eventId:this.newEventId(),eventType:"LOGIN_SUCCESS",identityId:t.id,scopeRef:e.scopeRef,result:"success",timestamp:u()}),{ok:!0,identity:Se(t),assignments:r}}async login(e){let t=await this.verifyCredential({principal:e.principal,secret:e.secret,verifyMethod:e.verifyMethod});if(!t.ok)throw A("AUTH_INVALID_CREDENTIAL",`Authentication failed: ${t.reasonCode}`);let i=[...t.assignments].sort((s,o)=>s.assignmentId.localeCompare(o.assignmentId))[0],r=await this.sessionService.createSession({identityId:t.identity.identityId,assignmentId:i==null?void 0:i.assignmentId,assuranceLevel:"basic"});return{identity:t.identity,sessionId:r.sessionId}}async logout(e){await this.sessionService.revokeSession({sessionId:e,reasonCode:"LOGOUT"}),await this.emitAudit({eventId:this.newEventId(),eventType:"SESSION_REVOKED",sessionId:e,result:"success",reasonCode:"LOGOUT",timestamp:u()})}};var M=class{constructor(e,t){this.db=e;this.options=t;this.newId=h("auth-session")}async resolveGrantedAssignments(e,t){let i=await this.db.query(a.assignments,{filters:{identityId:e,deleted:!1}});return t!=null&&t.tenantId?i.filter(r=>r.tenantId===t.tenantId):i}async createSession(e){var d,c,l,y;let t=u(),i=P(t,(d=e.ttlSeconds)!=null?d:$),r=await this.db.create(a.sessions,{id:this.newId(),identityId:e.identityId,activeAssignmentId:(c=e.assignmentId)!=null?c:null,assuranceLevel:(l=e.assuranceLevel)!=null?l:"basic",issuedAt:t,expiresAt:i,revokedAt:null,version:1,lastModified:t,deleted:!1}),s=await v(this.db,r.activeAssignmentId),o=await this.resolveGrantedAssignments(r.identityId,s);return(y=this.options.logger)==null||y.logInfo("[ofauth] session created",{sessionId:r.id,identityId:r.identityId}),E(r,s,o)}async refreshSession(e){var o;let t=await this.db.get(a.sessions,e.sessionId);if(!t||t.deleted||t.revokedAt)throw A("AUTH_SESSION_NOT_FOUND","Session not found");let i=await this.db.update(a.sessions,e.sessionId,{expiresAt:P(u(),(o=e.ttlSeconds)!=null?o:$),version:t.version+1,lastModified:u()}),r=await v(this.db,i.activeAssignmentId),s=await this.resolveGrantedAssignments(i.identityId,r);return E(i,r,s)}async revokeSession(e){var i,r;let t=await this.db.get(a.sessions,e.sessionId);!t||t.deleted||t.revokedAt||(await this.db.update(a.sessions,e.sessionId,{revokedAt:u(),version:t.version+1,lastModified:u()}),(r=this.options.logger)==null||r.logInfo("[ofauth] session revoked",{sessionId:e.sessionId,reasonCode:(i=e.reasonCode)!=null?i:null}))}async getActiveSession(e){let t=await this.db.get(a.sessions,e);if(!t||t.deleted||t.revokedAt||C(t.expiresAt))return null;let i=await v(this.db,t.activeAssignmentId),r=await this.resolveGrantedAssignments(t.identityId,i);return E(t,i,r)}};async function X(n,e={}){let t=new k(n,e),i=new M(n,e),r=new q(n,t),s=new N(n,t),o=new H(n,e,i,r,t);return{identityService:ce(o),sessionService:ue(i),contextService:le(r),authPolicyService:pe(s),authAuditService:t}}function je(){return new Date().toISOString()}function ge(n){return`${n}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}async function Ke(n,e){return n!=null&&n.hashPin?n.hashPin(e):`sha256:${e}`}async function $e(n){var I,R,p,w,L,ee,te,ne,ie,re,se,oe;let e=n.principal.trim();if(!e)throw new Error("AUTH_PROVISION_PRINCIPAL_REQUIRED");if(!((I=n.roleRef)!=null&&I.trim()))throw new Error("AUTH_PROVISION_ROLE_REQUIRED");let t=je(),i=await Ke(n.platformAdapter,n.secret),r=n.dbAdapter,o=(await r.query(a.identities,{filters:{principal:e,deleted:!1},limit:1}))[0],d=(R=o==null?void 0:o.id)!=null?R:ge("ofauth-identity");o?await r.update(a.identities,d,{secretHash:i,status:"active",lastModified:t}):await r.create(a.identities,{id:d,principal:e,secretHash:i,verifyMethod:"pin",status:"active",failedAttempts:0,lockoutUntil:null,version:1,lastModified:t,deleted:!1});let l=(await r.query(a.assignments,{filters:{identityId:d,deleted:!1},limit:1}))[0],y=(p=l==null?void 0:l.id)!=null?p:ge("ofauth-assignment"),g={source:(w=n.source)!=null?w:"host-app"};return l?await r.update(a.assignments,y,{roleRef:n.roleRef,tenantId:(ee=(L=n.scope)==null?void 0:L.tenantId)!=null?ee:null,branchId:(ne=(te=n.scope)==null?void 0:te.branchId)!=null?ne:null,scopeAttributes:g,lastModified:t}):await r.create(a.assignments,{id:y,identityId:d,roleRef:n.roleRef,tenantId:(re=(ie=n.scope)==null?void 0:ie.tenantId)!=null?re:null,branchId:(oe=(se=n.scope)==null?void 0:se.branchId)!=null?oe:null,scopeAttributes:g,version:1,lastModified:t,deleted:!1}),{identityId:d,assignmentId:y}}var Qe="phase2-runtime-logic";var Re=require("ofcore"),Z=require("ofcore"),B=require("ofcore");var Y=[{toVersion:1,up:async n=>{let e=K();for(let t of e)try{await n.addTable(t)}catch{}}}];var ze={logInfo(){},logWarn(){},logError(){}};async function J(n,e=ze){e.logInfo("[ofauth] starting database migration process");let t=[...Y].sort((s,o)=>s.toVersion-o.toVersion),i=t.length>0?t[t.length-1].toVersion:0,r=await n.getSchemaVersion();if((r==null||r<0)&&(r=0),r>=i){e.logInfo(`[ofauth] database already up-to-date at v${r}`);return}for(let s of t)s.toVersion>r&&(e.logInfo(`[ofauth] applying migration v${s.toVersion}`),await s.up(n),await n.setSchemaVersion(s.toVersion),r=s.toVersion);e.logInfo(`[ofauth] migration completed at v${r}`)}var V=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=(0,B.asReadonlyStore)(this.runtimeStateStore)}static builder(){return new F}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.start(e),this.domainServices=Ie(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async init(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.init(e),this.domainServices=Ie(this.runtime.domainServices),this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState({phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()}),t}}async stop(){this.runtimeStateStore.setState({phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()});try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState({phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()}),e}}isStarted(){return this.runtime.isStarted()}};function Ie(n){if(!n)throw new Error("Ofauth runtime started without domain services");return n}var F=class{constructor(){this.runtimeBuilder=Re.CoreRuntime.builder();this.domainServiceOverrides={};this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new Z.InMemoryDbAdapter)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}overrideDomainServices(e){return this.domainServiceOverrides={...this.domainServiceOverrides,...e},this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}withMigrationRunner(e){return this.withRuntimeHooks({runMigrations:e})}build(){var r;let e=(0,B.createStore)({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t=async s=>{var d,c;let o=(d=s.registry)==null?void 0:d.dbAdapter;o&&await J(o,(c=s.registry)==null?void 0:c.loggerAdapter)};this.runtimeBuilder.withHooks({...this.runtimeHooks,runMigrations:(r=this.runtimeHooks.runMigrations)!=null?r:t,createDomainServices:async s=>{var d,c,l,y;return{...this.domainServicesFactory?await this.domainServicesFactory():await X((c=(d=s.registry)==null?void 0:d.dbAdapter)!=null?c:new Z.InMemoryDbAdapter,{logger:(l=s.registry)==null?void 0:l.loggerAdapter,platformAdapter:(y=s.registry)==null?void 0:y.platformAdapter,emitActivity:async g=>{await s.emitActivity(g)}}),...this.domainServiceOverrides}}});let i=this.runtimeBuilder.build();return new V(i,e)}};
|
|
@@ -12,6 +12,15 @@ export interface ResolvedAuthContext {
|
|
|
12
12
|
roleRef?: string;
|
|
13
13
|
assuranceLevel: AssuranceLevel;
|
|
14
14
|
}
|
|
15
|
+
export interface AuthContextSummary {
|
|
16
|
+
assignmentStatus: 'assigned' | 'unassigned';
|
|
17
|
+
activeAssignmentId: string | null;
|
|
18
|
+
activeRoleRef: string | null;
|
|
19
|
+
activeTenantId: string | null;
|
|
20
|
+
activeBranchId: string | null;
|
|
21
|
+
activeDomainId: string | null;
|
|
22
|
+
assuranceLevel: AssuranceLevel | null;
|
|
23
|
+
}
|
|
15
24
|
export interface ProtectedRoutePolicy {
|
|
16
25
|
minimumAssuranceLevel?: AssuranceLevel;
|
|
17
26
|
requiredRoleRefs?: string[];
|
|
@@ -23,6 +32,14 @@ export interface ProtectedRouteGateResult {
|
|
|
23
32
|
allowed: boolean;
|
|
24
33
|
reasonCode?: 'NO_SESSION' | 'ASSURANCE_TOO_LOW' | 'ROLE_FORBIDDEN' | 'SCOPE_FORBIDDEN';
|
|
25
34
|
}
|
|
35
|
+
export declare function summarizeAuthScopeContext(input: {
|
|
36
|
+
scopeRef?: AuthScopeRef | null;
|
|
37
|
+
roleRef?: string | null;
|
|
38
|
+
assuranceLevel?: AssuranceLevel | null;
|
|
39
|
+
assignmentId?: string | null;
|
|
40
|
+
}): AuthContextSummary;
|
|
41
|
+
export declare function formatAuthContextSummary(summary: AuthContextSummary | null): string;
|
|
42
|
+
export declare function summarizeResolvedAuthContext(resolved: ResolvedAuthContext | null): AuthContextSummary | null;
|
|
26
43
|
export declare function loginWithResolvedContext(services: Pick<OfauthDomainServices, 'identityService' | 'sessionService' | 'contextService'>, input: {
|
|
27
44
|
principal: string;
|
|
28
45
|
secret: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ActivityRecord, DbAdapter, LoggerAdapter, PlatformAdapter } from 'ofcore';
|
|
2
2
|
import type { AuthAuditEvent } from '../../contracts/AuthAuditContract';
|
|
3
|
-
import type { AuthPolicySnapshot } from '../../contracts/AuthPolicyContract';
|
|
3
|
+
import type { AuthPolicySnapshot, StepUpRequirement } from '../../contracts/AuthPolicyContract';
|
|
4
4
|
import type { ContextAssignment } from '../../contracts/ContextContract';
|
|
5
5
|
import type { IdentityRef, IdentityStatus } from '../../contracts/IdentityContract';
|
|
6
6
|
import type { AssuranceLevel, SessionRef } from '../../contracts/SessionContract';
|
|
@@ -93,3 +93,4 @@ export declare function verifySecret(platformAdapter: PlatformAdapter | undefine
|
|
|
93
93
|
export declare function emitAuthActivity(options: ServiceRuntimeOptions, event: AuthAuditEvent): Promise<void>;
|
|
94
94
|
export declare function getAssignmentById(db: DbAdapter, id: string | null): Promise<AssignmentRow | null>;
|
|
95
95
|
export declare function fallbackPolicyProfiles(): AuthPolicySnapshot['profiles'];
|
|
96
|
+
export declare function fallbackStepUpRequirements(): StepUpRequirement[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofauth-shared-core",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Offline-first auth shared-core (identity/session/context/assurance) for of* domain modules.",
|
|
6
6
|
"author": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"bundle": "node esbuild.config.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"ofcore": "0.2.0-alpha.
|
|
39
|
+
"ofcore": "0.2.0-alpha.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"typescript": "^5.9.3",
|