@kanonak-protocol/sdk 5.8.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -41,7 +41,9 @@ export interface CredentialResolverDeps {
|
|
|
41
41
|
discover(host: string): Promise<OAuthServerMetadata | null>;
|
|
42
42
|
};
|
|
43
43
|
sessionManager?: {
|
|
44
|
-
getValidSession(host: string
|
|
44
|
+
getValidSession(host: string, opts?: {
|
|
45
|
+
forceRefresh?: boolean;
|
|
46
|
+
}): Promise<SessionRecord | null>;
|
|
45
47
|
};
|
|
46
48
|
/** The enrolled-authority hosts on this device — the trust-plane candidates (#75). */
|
|
47
49
|
deviceStore?: {
|
|
@@ -53,7 +55,11 @@ export declare class CredentialResolver {
|
|
|
53
55
|
private readonly sessions;
|
|
54
56
|
private readonly devices;
|
|
55
57
|
constructor(deps?: CredentialResolverDeps);
|
|
56
|
-
/** Resolve a fresh credential for `host`, or null to decline.
|
|
57
|
-
|
|
58
|
+
/** Resolve a fresh credential for `host`, or null to decline. `forceRefresh`
|
|
59
|
+
* re-mints the session from the cert (recovery when a cached token was revoked
|
|
60
|
+
* server-side — a caller learns this from a 401 on a resource read). */
|
|
61
|
+
resolve(host: string, opts?: {
|
|
62
|
+
forceRefresh?: boolean;
|
|
63
|
+
}): Promise<ResolvedCredential | null>;
|
|
58
64
|
private sessionFor;
|
|
59
65
|
}
|
|
@@ -42,8 +42,15 @@ export declare class SessionManager {
|
|
|
42
42
|
* the host issues no sessions or this device isn't enrolled there, so callers
|
|
43
43
|
* can attach a credential only where one exists (public hosts get none). A
|
|
44
44
|
* refresh that genuinely fails (network/server) propagates.
|
|
45
|
+
*
|
|
46
|
+
* `forceRefresh` skips the local cache and re-mints from the cert — the
|
|
47
|
+
* recovery path when a cached token isn't expired but the SERVER has revoked
|
|
48
|
+
* it (e.g. re-enrollment, deleted certs), which a caller learns only from a
|
|
49
|
+
* 401 on a resource read.
|
|
45
50
|
*/
|
|
46
|
-
getValidSession(host: string
|
|
51
|
+
getValidSession(host: string, opts?: {
|
|
52
|
+
forceRefresh?: boolean;
|
|
53
|
+
}): Promise<SessionRecord | null>;
|
|
47
54
|
/** Forget the cached session for `host`. */
|
|
48
55
|
clear(host: string): Promise<void>;
|
|
49
56
|
private sessionEndpoint;
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{a as Er,b as xr,c as Cr,d as Ar,e as ke}from"./chunk-TVSHIXLA.js";import{a as je,b as Me,c as Ve}from"./chunk-L2KE7B3K.js";import{a as Sn,c as ve,e as Le,h as Ue,i as Fe,j as vn}from"./chunk-IHB7UVEH.js";import{a as wr,b as br,c as Rr,d as
|
|
2
|
-
Run 'kanonak logout ${t}' then 'kanonak login ${t}' to fix.`)}}catch(r){if(He(r,44))return null;throw new Error(`macOS Keychain read failed for '${t}': ${
|
|
1
|
+
import{a as Er,b as xr,c as Cr,d as Ar,e as ke}from"./chunk-TVSHIXLA.js";import{a as je,b as Me,c as Ve}from"./chunk-L2KE7B3K.js";import{a as Sn,c as ve,e as Le,h as Ue,i as Fe,j as vn}from"./chunk-IHB7UVEH.js";import{a as wr,b as br,c as Rr,d as Y,e as Q,f as l,g as Pn,h as Pe,i as wn,j as bn}from"./chunk-VOJ6BGAR.js";import{a as kn}from"./chunk-EZSHR3CB.js";import"./chunk-QHABFCRC.js";import{a as It,b as Nt,c as Bt,d as Ot,e as jt,f as Jt,g as qt,h as Xt,i as Zt}from"./chunk-CC44JAOT.js";import{a as Mt,b as Vt,c as Lt,d as Ut,e as A,f as Ft,h as Ht,j as zt,k as Gt}from"./chunk-UXYCUGSF.js";import{a as Kt}from"./chunk-4NO7MHS7.js";import{a as Tr,b as $r,c as _r,d as Kr}from"./chunk-S6VSAKXB.js";import{a as Ir,b as Lr}from"./chunk-PEUTCG3B.js";import{a as Br}from"./chunk-PEJALHXK.js";import{a as Wt}from"./chunk-SC5M74NM.js";import{A as yn,B as hn,K as gn,a as Ur,b as Fr,c as Hr,d as zr,e as Wr,f as Gr,g as Jr,h as qr,i as Xr,j as Zr,k as Yr,l as Qr,m as en,n as tn,o as rn,p as nn,q as on,r as sn,s as an,t as cn,u as ln,v as dn,w as pn,x as un,y as mn,z as fn}from"./chunk-7K5TAJ44.js";import"./chunk-ITKOKDBG.js";import{a as T,b as tr,c as dr,h as mr,i as fr,j as Sr,k as vr,l as U}from"./chunk-MX3DEXMV.js";import{a as j}from"./chunk-NJ3AZYQD.js";import{a as Pr,b as Se,c as Nr,d as P,e as Or,f as jr,g as Mr,h as Vr}from"./chunk-ZP6P7HNU.js";import{a as Oe}from"./chunk-6U26UASC.js";import{a as pr,b as ur,c as L,d as yr,e as hr,g as gr,k as kr}from"./chunk-GZPLWII7.js";import{a as Yt,b as Qt,c as D,d as M,e as rr,f as nr,g as or,h as sr,i as ir,j as ar,k as cr,l as lr,r as Z,w as V,x as he,y as ge}from"./chunk-7BHDZHJY.js";import{a as er}from"./chunk-FUUTGGJS.js";import{a as xt,b as ye,c as X,d as Ct,e as R,f as At,g as Dt,h as Tt,i as $t,j as _t}from"./chunk-2ACBWC7K.js";import{a as Dr}from"./chunk-ODIECDN7.js";import{VersionOperator as aa}from"@kanonak-protocol/types/document/models/enums";import{existsSync as zn,readFileSync as Wn}from"fs";import{homedir as Gn}from"os";import{join as Jn}from"path";import{execFile as Rn}from"child_process";import{promisify as En}from"util";var ee=En(Rn),xn="kanonak",te="/usr/bin/security",m=class{constructor(e=xn){this.service=e}service;async get(e){let t=l(e);try{let{stdout:r}=await ee(te,["find-generic-password","-s",this.service,"-a",t,"-w"],{timeout:1e4});try{return JSON.parse(r.trim())}catch{throw new Error(`Stored credential for '${t}' is corrupted (not valid JSON).
|
|
2
|
+
Run 'kanonak logout ${t}' then 'kanonak login ${t}' to fix.`)}}catch(r){if(He(r,44))return null;throw new Error(`macOS Keychain read failed for '${t}': ${re(r)}
|
|
3
3
|
The Keychain may be locked or inaccessible.
|
|
4
|
-
Try unlocking it via Keychain Access.app or running 'security unlock-keychain'.`)}}async store(e,t){let r=
|
|
4
|
+
Try unlocking it via Keychain Access.app or running 'security unlock-keychain'.`)}}async store(e,t){let r=l(e),n=JSON.stringify(t);try{await ee(te,["add-generic-password","-s",this.service,"-a",r,"-U","-w",n],{timeout:1e4})}catch(s){throw new Error(`macOS Keychain write failed for '${r}': ${re(s)}
|
|
5
5
|
Ensure the Keychain is unlocked and the CLI has write permission.
|
|
6
|
-
On managed devices, your IT policy may block credential storage.`)}}async remove(e){let t=
|
|
7
|
-
The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await
|
|
8
|
-
`))if(n.includes(`"svce"<blob>="${this.service}"`)&&(r=!0),r&&n.includes('"acct"<blob>=')){let s=n.match(/"acct"<blob>="([^"]+)"/);s&&t.push(s[1]),r=!1}return t}catch(e){return console.warn(` Warning: Could not enumerate Keychain entries: ${
|
|
9
|
-
${
|
|
6
|
+
On managed devices, your IT policy may block credential storage.`)}}async remove(e){let t=l(e);try{await ee(te,["delete-generic-password","-s",this.service,"-a",t],{timeout:1e4})}catch(r){if(He(r,44))return;console.warn(` Warning: macOS Keychain delete failed for '${t}': ${re(r)}
|
|
7
|
+
The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await ee(te,["dump-keychain"],{timeout:1e4}),t=[],r=!1;for(let n of e.split(`
|
|
8
|
+
`))if(n.includes(`"svce"<blob>="${this.service}"`)&&(r=!0),r&&n.includes('"acct"<blob>=')){let s=n.match(/"acct"<blob>="([^"]+)"/);s&&t.push(s[1]),r=!1}return t}catch(e){return console.warn(` Warning: Could not enumerate Keychain entries: ${re(e)}`),[]}}};function He(o,e){return typeof o=="object"&&o!==null&&"code"in o&&o.code===e}function re(o){return o instanceof Error?o.message:String(o)}import{execFile as Cn}from"child_process";import{promisify as An}from"util";var Dn=An(Cn),Tn="kanonak:",ze=2560,f=class{constructor(e=Tn){this.targetPrefix=e}targetPrefix;async get(e){let t=this.targetPrefix+l(e),r=`
|
|
9
|
+
${oe}
|
|
10
10
|
$target = $env:KANONAK_CRED_TARGET
|
|
11
11
|
$ptr = [IntPtr]::Zero
|
|
12
12
|
$result = [CredMan]::CredRead($target, 1, 0, [ref]$ptr)
|
|
@@ -18,8 +18,8 @@ try {
|
|
|
18
18
|
[System.Text.Encoding]::Unicode.GetString($bytes)
|
|
19
19
|
} finally {
|
|
20
20
|
[CredMan]::CredFree($ptr)
|
|
21
|
-
}`;try{let{stdout:n}=await
|
|
22
|
-
${
|
|
21
|
+
}`;try{let{stdout:n}=await ne(r,{KANONAK_CRED_TARGET:t}),s=n.trim();return s?JSON.parse(s):null}catch{return null}}async store(e,t){let r=this.targetPrefix+l(e),n=JSON.stringify(t),s=Buffer.byteLength(n,"utf16le");if(s>ze)throw new Error(`Credential '${r}' is ${s} bytes (UTF-16), over the Windows Credential Manager limit of ${ze} (CRED_MAX_CREDENTIAL_BLOB_SIZE). Keep only the secret here and store large/public material (certificates, chains) on disk.`);let i=`
|
|
22
|
+
${oe}
|
|
23
23
|
$target = $env:KANONAK_CRED_TARGET
|
|
24
24
|
$json = $env:KANONAK_CRED_JSON
|
|
25
25
|
$bytes = [System.Text.Encoding]::Unicode.GetBytes($json)
|
|
@@ -35,11 +35,11 @@ try {
|
|
|
35
35
|
if (-not $result) { throw "CredWrite failed (Win32 error $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error()))" }
|
|
36
36
|
} finally {
|
|
37
37
|
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($cred.CredentialBlob)
|
|
38
|
-
}`;try{await
|
|
39
|
-
${
|
|
38
|
+
}`;try{await ne(i,{KANONAK_CRED_TARGET:r,KANONAK_CRED_JSON:n})}catch(a){let c=a,d=c.stderr&&c.stderr.trim()||c.message||String(a);throw new Error(`Windows Credential Manager write failed: ${d}`)}}async remove(e){let t=this.targetPrefix+l(e),r=`
|
|
39
|
+
${oe}
|
|
40
40
|
$target = $env:KANONAK_CRED_TARGET
|
|
41
|
-
[CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await
|
|
42
|
-
${
|
|
41
|
+
[CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await ne(r,{KANONAK_CRED_TARGET:t})}catch{}}async list(){let e=`
|
|
42
|
+
${oe}
|
|
43
43
|
${$n}
|
|
44
44
|
$prefix = $env:KANONAK_CRED_PREFIX
|
|
45
45
|
$count = 0
|
|
@@ -57,8 +57,8 @@ if ([CredMan]::CredEnumerate(($prefix + "*"), 0, [ref]$count, [ref]$pCreds)) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
[CredMan]::CredFree($pCreds)
|
|
60
|
-
}`;try{let{stdout:t}=await
|
|
61
|
-
`).map(r=>r.trim()).filter(Boolean)}catch{return[]}}};async function
|
|
60
|
+
}`;try{let{stdout:t}=await ne(e,{KANONAK_CRED_PREFIX:this.targetPrefix});return t.trim().split(`
|
|
61
|
+
`).map(r=>r.trim()).filter(Boolean)}catch{return[]}}};async function ne(o,e){let t=Buffer.from(o,"utf16le").toString("base64");for(let r of["pwsh","powershell"])try{return await Dn(r,["-NoProfile","-NonInteractive","-EncodedCommand",t],{timeout:15e3,...e&&{env:{...process.env,...e}}})}catch(n){if(r==="powershell")throw n}throw new Error("Neither pwsh nor powershell found")}var oe=`
|
|
62
62
|
Add-Type -TypeDefinition @"
|
|
63
63
|
using System;
|
|
64
64
|
using System.Runtime.InteropServices;
|
|
@@ -89,14 +89,14 @@ public class CredMan {
|
|
|
89
89
|
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
90
90
|
public static extern bool CredEnumerate(string filter, int flags, out int count, out IntPtr credentials);
|
|
91
91
|
}
|
|
92
|
-
"@`,$n="";import{execFile as _n,spawn as Kn}from"child_process";import{promisify as In}from"util";var
|
|
93
|
-
`)){let n=r.match(/attribute\.publisher\s*=\s*(.+)/);n&&t.push(n[1].trim())}return t}catch{return[]}}};async function E(){try{return await
|
|
92
|
+
"@`,$n="";import{execFile as _n,spawn as Kn}from"child_process";import{promisify as In}from"util";var se=In(_n),Nn="kanonak",y=class{constructor(e=Nn){this.service=e}service;async get(e){let t=l(e);try{let{stdout:r}=await se("secret-tool",["lookup","service",this.service,"publisher",t],{timeout:1e4}),n=r.trim();return n?JSON.parse(n):null}catch{return null}}async store(e,t){let r=l(e),n=JSON.stringify(t);await new Promise((s,i)=>{let a=Kn("secret-tool",["store","--label",`Kanonak: ${r}`,"service",this.service,"publisher",r],{stdio:["pipe","ignore","ignore"],timeout:1e4});a.stdin.write(n),a.stdin.end(),a.on("close",c=>{c===0?s():i(new Error(`secret-tool store exited with code ${c}`))}),a.on("error",i)})}async remove(e){let t=l(e);try{await se("secret-tool",["clear","service",this.service,"publisher",t],{timeout:1e4})}catch{}}async list(){try{let{stdout:e}=await se("secret-tool",["search","service",this.service],{timeout:1e4}),t=[];for(let r of e.split(`
|
|
93
|
+
`)){let n=r.match(/attribute\.publisher\s*=\s*(.+)/);n&&t.push(n[1].trim())}return t}catch{return[]}}};async function E(){try{return await se("sh",["-c","command -v secret-tool"],{timeout:5e3}),!0}catch{return!1}}import{existsSync as We,mkdirSync as Ge,readFileSync as Je,writeFileSync as qe}from"fs";import{createCipheriv as Bn,createDecipheriv as On,randomBytes as Xe}from"crypto";import{homedir as jn}from"os";import{join as Re,dirname as Ze}from"path";var Qe=Re(jn(),".config","kanonak"),F=Re(Qe,"keyring.key"),Mn=Re(Qe,"credentials.enc"),Ye="aes-256-gcm",we=32,$=12,be=16,h=class{constructor(e=Mn){this.secretsFile=e}secretsFile;async get(e){let t=this.loadStore(),r=l(e);return t[r]??null}async store(e,t){let r=this.loadStore(),n=l(e);r[n]=t,this.saveStore(r)}async remove(e){let t=this.loadStore(),r=l(e);delete t[r],this.saveStore(t)}async list(){let e=this.loadStore();return Object.keys(e)}loadStore(){if(!We(this.secretsFile))return{};try{let e=this.getOrCreateKey(),t=Je(this.secretsFile);if(t.length<$+be)return{};let r=t.subarray(0,$),n=t.subarray($,$+be),s=t.subarray($+be),i=On(Ye,e,r);i.setAuthTag(n);let a=Buffer.concat([i.update(s),i.final()]);return JSON.parse(a.toString("utf-8"))}catch{return{}}}saveStore(e){let t=this.getOrCreateKey(),r=Xe($),n=Bn(Ye,t,r),s=Buffer.from(JSON.stringify(e),"utf-8"),i=Buffer.concat([n.update(s),n.final()]),a=n.getAuthTag(),c=Buffer.concat([r,a,i]);Ge(Ze(this.secretsFile),{recursive:!0}),qe(this.secretsFile,c,{mode:384})}getOrCreateKey(){if(We(F)){let t=Je(F);if(t.length!==we)throw new Error(`Credential keyring key is corrupted (expected ${we} bytes, got ${t.length}). Delete ${F} and re-authenticate.`);return t}let e=Xe(we);return Ge(Ze(F),{recursive:!0}),qe(F,e,{mode:384}),e}};import{execFile as Vn}from"child_process";import{promisify as Ln}from"util";var Un=Ln(Vn),et=3e4,H=class{constructor(e){this.helperPath=e}helperPath;async get(e){let t=l(e);try{let n=(await this.runHelper("get",{publisher:t})).trim();return n?JSON.parse(n):null}catch(r){throw new Error(`Credential helper '${this.helperPath}' failed to read credential for '${t}': ${ie(r)}
|
|
94
94
|
Verify the helper binary exists, is executable, and implements the Kanonak credential helper protocol.
|
|
95
|
-
Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,t){let r=
|
|
96
|
-
Verify the helper binary supports the 'store' action.`)}}async remove(e){let t=
|
|
95
|
+
Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,t){let r=l(e);try{await this.runHelper("store",{publisher:r,credential:t})}catch(n){throw new Error(`Credential helper '${this.helperPath}' failed to store credential for '${r}': ${ie(n)}
|
|
96
|
+
Verify the helper binary supports the 'store' action.`)}}async remove(e){let t=l(e);try{await this.runHelper("erase",{publisher:t})}catch(r){console.warn(` Warning: Credential helper '${this.helperPath}' failed to erase credential for '${t}': ${ie(r)}`)}}async list(){try{let e=await this.runHelper("list",void 0);return JSON.parse(e.trim())}catch(e){return console.warn(` Warning: Credential helper '${this.helperPath}' failed to list credentials: ${ie(e)}`),[]}}async runHelper(e,t){try{let{stdout:r}=await Un(this.helperPath,[e],{...t&&{input:JSON.stringify(t)},timeout:et});return r}catch(r){throw Fn(r)?new Error(`Credential helper not found at '${this.helperPath}'.
|
|
97
97
|
Check the 'credentialHelper' path in ~/.kanonak/config.json.`):Hn(r)?new Error(`Credential helper '${this.helperPath}' timed out after ${et/1e3}s on '${e}'.
|
|
98
|
-
The helper may be waiting for authentication to an external vault.`):r}}};function
|
|
99
|
-
Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{homedir as ot}from"os";import{join as x}from"path";import{mkdir as Zn,writeFile as tt,readFile as rt,rm as nt}from"fs/promises";var xe="kanonak-device",Yn=x(ot(),".config","kanonak","device-credentials.enc"),Qn=x(ot(),".kanonak","devices"),w=class{constructor(e={}){this.deps=e}deps;backend=null;backendReady=null;certDir(e){let t=
|
|
98
|
+
The helper may be waiting for authentication to an external vault.`):r}}};function ie(o){return o instanceof Error?o.message:String(o)}function Fn(o){return o instanceof Error&&"code"in o&&o.code==="ENOENT"}function Hn(o){return o instanceof Error&&"killed"in o&&o.killed}var Ee=Jn(Gn(),".kanonak","config.json"),ae=class{backend=null;backendReady=null;async getBackend(){if(this.backend)return this.backend;if(this.backendReady)return this.backendReady;this.backendReady=this.resolveBackend();try{return this.backend=await this.backendReady,this.backend}catch(e){throw this.backendReady=null,e}}async getToken(e){let t=qn(e);if(t)return t;let n=await(await this.getBackend()).get(e);return!n||!Q(n)?null:n.accessToken??null}async getCredential(e){return(await this.getBackend()).get(e)}async store(e,t){return(await this.getBackend()).store(e,t)}async remove(e){return(await this.getBackend()).remove(e)}async list(){return(await this.getBackend()).list()}async resolveBackend(){let e=Xn();return e.credentialHelper?new H(e.credentialHelper):process.platform==="darwin"?new m:process.platform==="win32"?new f:await E()?new y:new h}};function qn(o){let t="KANONAK_TOKEN_"+l(o).replace(/[.\-]/g,"_").toUpperCase();return process.env[t]??null}function Xn(){if(!zn(Ee))return{};try{return JSON.parse(Wn(Ee,"utf-8"))}catch(o){let e=o instanceof Error?o.message:String(o);return console.warn(` Warning: Failed to parse ${Ee}: ${e}
|
|
99
|
+
Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{homedir as ot}from"os";import{join as x}from"path";import{mkdir as Zn,writeFile as tt,readFile as rt,rm as nt}from"fs/promises";var xe="kanonak-device",Yn=x(ot(),".config","kanonak","device-credentials.enc"),Qn=x(ot(),".kanonak","devices"),w=class{constructor(e={}){this.deps=e}deps;backend=null;backendReady=null;certDir(e){let t=l(e).replace(/[^a-zA-Z0-9._-]/g,"_");return x(this.deps.certBaseDir??Qn,t)}async getBackend(){if(this.backend)return this.backend;if(this.backendReady)return this.backendReady;this.backendReady=this.resolveBackend();try{return this.backend=await this.backendReady,this.backend}catch(e){throw this.backendReady=null,e}}async get(e){let t=await(await this.getBackend()).get(e);if(!t)return null;if(typeof t.certificatePem=="string"&&typeof t.chainPem=="string")return t;let r=this.certDir(e),n,s;try{n=await rt(x(r,"cert.pem"),"utf-8"),s=await rt(x(r,"chain.pem"),"utf-8")}catch{return null}return{...t,certificatePem:n,chainPem:s}}async store(e,t){let{certificatePem:r,chainPem:n,...s}=t,i=this.certDir(e);await Zn(i,{recursive:!0}),await tt(x(i,"cert.pem"),r,"utf-8"),await tt(x(i,"chain.pem"),n,"utf-8");try{await(await this.getBackend()).store(e,s)}catch(a){throw await nt(i,{recursive:!0,force:!0}).catch(()=>{}),a}}async remove(e){await(await this.getBackend()).remove(e),await nt(this.certDir(e),{recursive:!0,force:!0})}async list(){return(await this.getBackend()).list()}async resolveBackend(){return this.deps.backend?this.deps.backend:process.platform==="darwin"?new m(xe):process.platform==="win32"?new f(`${xe}:`):await E()?new y(xe):new h(Yn)}};import{homedir as eo}from"os";import{join as to}from"path";var Ce="kanonak-session",ro=to(eo(),".config","kanonak","session-credentials.enc"),_=class{constructor(e={}){this.deps=e}deps;backend=null;backendReady=null;async getBackend(){if(this.backend)return this.backend;if(this.backendReady)return this.backendReady;this.backendReady=this.resolveBackend();try{return this.backend=await this.backendReady,this.backend}catch(e){throw this.backendReady=null,e}}async get(e){return(await this.getBackend()).get(e)}async store(e,t){return(await this.getBackend()).store(e,t)}async remove(e){return(await this.getBackend()).remove(e)}async list(){return(await this.getBackend()).list()}async resolveBackend(){return this.deps.backend?this.deps.backend:process.platform==="darwin"?new m(Ce):process.platform==="win32"?new f(`${Ce}:`):await E()?new y(Ce):new h(ro)}};function ce(o,e=5*6e4,t=Date.now()){let r=Date.parse(o.expiresAt);return Number.isNaN(r)?!0:t>=r-e}var st="key_thumbprint",b=class{cache=new Map;prCache=new Map;async discoverProtectedResource(e){let t=l(e);if(this.prCache.has(t))return this.prCache.get(t);let r=`https://${t}/.well-known/oauth-protected-resource`,n=await no(r),s=n&&Array.isArray(n.authorization_servers)?n.authorization_servers.filter(a=>typeof a=="string"):[],i=s.length>0?s:null;return this.prCache.set(t,i),i}async discover(e){let t=l(e);if(this.cache.has(t))return this.cache.get(t);let r=`https://${t}/.well-known/oauth-authorization-server`,n=await this.tryEndpoint(r);if(!n){let s=`https://${t}/.well-known/openid-configuration`;n=await this.tryEndpoint(s)}return this.cache.set(t,n),n}async supportsOAuth(e){return await this.discover(e)!==null}static supportsPkceS256(e){return e.codeChallengeMethodsSupported?.some(t=>t.toUpperCase()==="S256")??!1}static supportsDynamicRegistration(e){return!!e.registrationEndpoint}static supportsAuthorizationCode(e){return e.responseTypesSupported?.some(t=>t.toLowerCase()==="code")??!1}static supportsEnrollment(e){return!!e.enrollmentEndpoint}static supportsSession(e){return!!e.sessionEndpoint}async tryEndpoint(e){let t;try{t=await fetch(e)}catch(n){let s=n instanceof Error?n.message:String(n);return s.includes("ENOTFOUND")||s.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${s})`),console.error(" If the server is behind a VPN, ensure you are connected.")):s.includes("CERT")||s.includes("SSL")||s.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${s})`),console.error(" If using a custom CA certificate, set NODE_EXTRA_CA_CERTS=/path/to/ca.pem")):console.error(` OAuth discovery: ${e} \u2014 network error: ${s}`),null}if(!t.ok)return t.status===404||(t.status===403?(console.error(` OAuth discovery: ${e} \u2014 HTTP 403 Forbidden`),console.error(" Access may be blocked by a firewall, proxy, or WAF.")):t.status>=500&&(console.error(` OAuth discovery: ${e} \u2014 HTTP ${t.status} server error`),console.error(" The authorization server returned an internal error. Contact your IDP administrator."))),null;let r;try{r=await t.json()}catch{return console.error(` OAuth discovery: ${e} \u2014 response is not valid JSON`),console.error(" The endpoint may be returning HTML instead of JSON. Check IDP configuration."),null}return{issuer:g(r.issuer),authorizationEndpoint:g(r.authorization_endpoint),tokenEndpoint:g(r.token_endpoint),registrationEndpoint:g(r.registration_endpoint),revocationEndpoint:g(r.revocation_endpoint),scopesSupported:k(r.scopes_supported),responseTypesSupported:k(r.response_types_supported),grantTypesSupported:k(r.grant_types_supported),codeChallengeMethodsSupported:k(r.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:k(r.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:k(r.dpop_signing_alg_values_supported),enrollmentEndpoint:g(r.enrollment_endpoint),enrollmentIssuanceProtocols:k(r.enrollment_issuance_protocols),enrollmentKeyTypes:k(r.enrollment_key_types),enrollmentScopesSupported:k(r.enrollment_scopes_supported),enrollmentConsentBindingParam:g(r.enrollment_consent_binding_param),sessionEndpoint:g(r.session_endpoint),sessionEndpointAuthMethod:g(r.session_endpoint_auth_method)}}};async function no(o){try{let e=await fetch(o);return e.ok?await e.json():null}catch{return null}}function g(o){return typeof o=="string"?o:null}function k(o){return Array.isArray(o)?o.filter(e=>typeof e=="string"):null}import*as it from"https";import{createPrivateKey as oo}from"crypto";var S=class extends Error{},K=class{constructor(e=ao){this.transport=e}transport;async exchange(e,t,r={}){let n=io(t.keyMaterial),s="{}",i;try{i=await this.transport({url:e,certPem:so(t),keyPem:n,body:s,contentType:"application/json"})}catch(p){throw new S(`mTLS session exchange to ${e} failed: ${p.message}`)}if(i.status<200||i.status>=300){let p=i.status===401?" \u2014 the gateway did not accept the device client certificate (invalid_client)":"";throw new S(`Session endpoint ${e} returned HTTP ${i.status}${p}: ${i.body.slice(0,300)}`)}let a;try{a=JSON.parse(i.body)}catch{throw new S(`Session endpoint returned a non-JSON response: ${i.body.slice(0,200)}`)}if(typeof a.access_token!="string"||!a.access_token)throw new S("Session response had no access_token.");let c=typeof a.expires_in=="number"?a.expires_in:0,d=r.nowMs??Date.now();return{token:a.access_token,tokenType:typeof a.token_type=="string"&&a.token_type?a.token_type:"Bearer",expiresAt:new Date(d+c*1e3).toISOString(),scope:typeof a.scope=="string"?a.scope:""}}};function so(o){let e=o.chainPem.trim();return e?`${o.certificatePem.replace(/\s+$/,"")}
|
|
100
100
|
${e}
|
|
101
|
-
`:o.certificatePem}function io(o){try{return oo({key:o,format:"jwk"}).export({type:"pkcs8",format:"pem"})}catch(e){throw new S(`The device key is not an exportable software private key, so it cannot present mTLS in software (a future hardware key provider would do the handshake itself): ${e.message}`)}}var ao=o=>new Promise((e,t)=>{let r=new URL(o.url),n=it.request({method:"POST",hostname:r.hostname,port:r.port||443,path:r.pathname+r.search,cert:o.certPem,key:o.keyPem,headers:{"Content-Type":o.contentType,"Content-Length":Buffer.byteLength(o.body),Accept:"application/json"},timeout:3e4},s=>{let i=[];s.on("data",a=>i.push(a)),s.on("end",()=>e({status:s.statusCode??0,body:Buffer.concat(i).toString("utf-8")}))});n.on("error",t),n.on("timeout",()=>n.destroy(new Error("mTLS request timed out"))),n.write(o.body),n.end()});var
|
|
102
|
-
The stored key pair may be corrupted. Run 'kanonak login ${r}' to re-authenticate.`),i.Authorization=`Bearer ${s.accessToken}`}}else i.Authorization=`Bearer ${s.accessToken}`;let a=await C(t,{method:n,headers:i});if(a.status===401&&s.dpopKeyPair){let l=a.headers.get("DPoP-Nonce");if(l){e.set(r,l);try{let d=H(s.dpopKeyPair.privateKey,s.dpopKeyPair.publicKey,n,t,s.accessToken,l);i.DPoP=d,a=await C(t,{method:n,headers:i})}catch{}}}return a}}import*as Ae from"js-yaml";import{VersionOperator as pt}from"@kanonak-protocol/types/document/models/enums";var ho="0.0.0",N=class{constructor(e,t=new O,r){this.repository=e;this.parser=t;this.objectParser=r??new L(this.parser)}repository;parser;objectParser;imports(){return new z}serializeValue(e,t){return yt(e,t)}async buildContentAddressed(e){let t=e.book.toImports(),r=await this.hashBody(e.publisher,t,e.body),n=De(r),s={type:"EphemeralPackage",publisher:e.publisher,imports:t};e.contentHashProperty&&(s[e.contentHashProperty]=r),Object.assign(s,e.header??{}),s.imports=t;let i={[n]:s,...e.body},a=this.dump(i);return{yaml:a,byteCount:mt(a),contentHash:r,packageName:n,publisher:e.publisher,resourceCount:Object.keys(e.body).length}}async buildNamed(e){let t=e.book.toImports(),r={type:e.type??"Package",publisher:e.publisher,version:e.version,imports:t},n;e.contentHashProperty&&(n=await this.hashBody(e.publisher,t,e.body),r[e.contentHashProperty]=n),Object.assign(r,e.header??{}),r.imports=t;let s={[e.name]:r,...e.body},i=this.dump(s),a={yaml:i,byteCount:mt(i),packageName:e.name,publisher:e.publisher,resourceCount:Object.keys(e.body).length};return n!==void 0&&(a.contentHash=n),a}dump(e){return Ae.dump(e,{lineWidth:-1})}async hashBody(e,t,r){let n={[ut]:{type:"EphemeralPackage",publisher:e,imports:t},...r},s=this.parser.parse(Ae.dump(n,{lineWidth:-1})),i=s.metadata.namespace_?.toString(),l=(await this.objectParser.parseKanonaks(new Oe(s,this.repository))).filter(d=>d instanceof A&&d.namespace===i&&d.name!==ut);for(let d of l)d.namespace="ephemeral";return Pe(l)}},ut="__pkgbuilder_probe__";function mt(o){return new TextEncoder().encode(o).length}function De(o){let e="sha256:",t=o.startsWith(e)?e.length:0;return`q-${o.slice(t,t+16)}`}var z=class{byKey=new Map;aliases=new Set;ensure(e,t,r,n,s=pt.Major){let i=`${e}/${t}@${r}`,a=this.byKey.get(i);if(a)return a.alias;let l=this.uniqueAlias(n);return this.byKey.set(i,{publisher:e,package_:t,version:r,alias:l,match:s}),l}ref(e){if(!e.version||typeof e.version.major!="number")throw new Error(`Cannot serialize a reference to ${e.publisher}/${e.package_}/${e.name} without a version.`);return`${this.ensure(e.publisher,e.package_,R(e.version),e.package_)}.${e.name}`}refLatest(e,t,r,n){return`${this.ensure(e,t,ho,n??t,pt.Any)}.${r}`}toImports(){let e=new Map;for(let r of this.byKey.values()){let n=e.get(r.publisher)??[];n.push(r),e.set(r.publisher,n)}return[...e.keys()].sort().map(r=>({publisher:r,packages:e.get(r).sort((n,s)=>n.package_<s.package_?-1:1).map(n=>({package:n.package_,match:fe(n.match),version:n.version,alias:n.alias}))}))}uniqueAlias(e){let t=W(e)||"pkg",r=t,n=2;for(;this.aliases.has(r);)r=`${t}${n++}`;return this.aliases.add(r),r}};function yt(o,e){if(o!=null){if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o;if(o instanceof j)return e.ref(o.subject);if(Array.isArray(o)){let t=o.map(r=>yt(r,e)).filter(r=>r!==void 0);return t.length>0?t:void 0}if(o instanceof D)throw new Error("Embedded values are not yet supported by PackageBuilder. Produce a literal or a reference, or compose the embedded shape into the output class.");if(go(o))throw new Error(`Value produced a bare URI without a version (${o.publisher}/${o.package_}/${o.name}); cannot serialize it as a reference.`)}}function W(o){return o.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function go(o){return typeof o=="object"&&o!==null&&typeof o.publisher=="string"&&typeof o.package_=="string"&&typeof o.name=="string"}var le=class{constructor(e){this.producers=e}producers;produced=new Map;producerFor(e,t){return this.producers.find(r=>r.canProduce(e,t))}async produceCached(e,t,r,n){let s=`${t}/${r}@${R(n)}`,i=this.produced.get(s);if(i)return i;let{document:a}=await e.produce(t,r,n);return this.produced.set(s,a),a}async getHighestCompatibleVersionAsync(e,t){let r=this.producerFor(e,t.packageName);if(!r)return null;let n={operator:t.versionOperator,version:t.version},s=await r.resolveVersion(e,t.packageName,n);return s?this.produceCached(r,e,t.packageName,s):null}async getDocumentAsync(e){let t;try{t=Se(e)}catch{return null}if(t.kind!=="package"||!t.version)return null;let r=this.producerFor(t.publisher,t.package_);return r?this.produceCached(r,t.publisher,t.package_,t.version):null}async getDocumentsByNamespaceAsync(e,t){return Array.from(this.produced.values()).filter(r=>{let n=r.metadata.namespace_;return n!=null&&n.publisher===e&&n.package_===t})}async getAllDocumentsAsync(){return Array.from(this.produced.values())}async saveDocumentAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async deleteDocumentAsync(e){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async clearNamespaceAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(e){return null}async getDocumentUriAsync(e){return null}};var Te={async authorize(){return{allowed:!0}}},$e={async record(){}},G=class extends Error{constructor(t,r){let n=`${t.publisher}/${t.package_}${t.version?`@${t.version.major}.${t.version.minor}.${t.version.patch}`:""}`;super(`Not entitled to produce ${n}${r?`: ${r}`:""}`);this.address=t;this.reason=r;this.name="EntitlementDeniedError"}address;reason},de=class{inner;ctx;policy;meter;constructor(e,t,r=Te,n=$e){this.inner=e,this.ctx=t,this.policy=r,this.meter=n}canProduce(e,t){return this.inner.canProduce(e,t)}async resolveVersion(e,t,r){return await this.assertAllowed({publisher:e,package_:t,version:r.version}),this.inner.resolveVersion(e,t,r)}async produce(e,t,r){let n={publisher:e,package_:t,version:r};await this.assertAllowed(n);let s=await this.inner.produce(e,t,r);return await this.meter.record(this.ctx,n,s),s}async assertAllowed(e){let t=await this.policy.authorize(this.ctx,e);if(!t.allowed)throw new G(e,t.reason)}};var u="kanonak.org",v="view",ft="core-kanonak",ko={publisher:u,package_:v,name:"rootView"},So={publisher:u,package_:v,name:"bind"},vo={publisher:u,package_:v,name:"produces"},Po={publisher:u,package_:v,name:"projections"},wo={publisher:u,package_:v,name:"where"},bo={publisher:u,package_:v,name:"value"},Ro={publisher:u,package_:v,name:"as"},pe=class{constructor(e,t=new O){this.repository=e;this.parser=t;this.objectParser=new L(this.parser),this.builder=new N(this.repository,this.parser,this.objectParser)}repository;parser;objectParser;builder;async materialize(e,t={}){let r=await this.objectParser.parseKanonaks(this.repository),n=this.resolveView(r,e),s=M(n,So);if(!s)throw new Error(`View ${n.namespace}/${n.name} declares no view.bind; cannot materialize.`);let i=M(n,vo);if(!i)throw new Error(`View ${n.namespace}/${n.name} is a selection view (no view.produces). In-graph materialization of selection views is not yet supported \u2014 declare a view.produces output class to reshape the result.`);let a=Eo(n),l=ht(r,u,ft),d=ht(r,u,v),p=this.builder.imports(),ue=p.ensure(u,ft,l,"ck"),kt=p.ensure(u,v,d,"v"),St=p.ref(i),vt=new Fe(this.repository,this.parser,this.objectParser),_e=new Le(vt,r),Pt=this.readProjections(r,n),wt=Ao(n,wo),bt=this.findInstances(r,s,await this.reason(t)),Ke={},Rt=new Set;for(let J of bt){if(!await this.passesWhere(_e,r,wt,J))continue;let ye={type:St};for(let Ne of Pt){let Et=await this.evaluateValue(_e,r,Ne.value,J),Be=this.builder.serializeValue(gt(Et),p);Be!==void 0&&(ye[p.ref(Ne.as)]=Be)}let Ie=P(J);Ie&&(ye[`${kt}.derivedFrom`]=p.ref(Ie)),Ke[this.rowName(J,Rt)]=ye}let me={};t.resolvedAt&&(me[`${ue}.resolvedAt`]=t.resolvedAt),t.invocationId&&(me[`${ue}.id`]=t.invocationId);let B=await this.builder.buildContentAddressed({publisher:a,book:p,body:Ke,contentHashProperty:`${ue}.contentHash`,header:me});return{yaml:B.yaml,contentHash:B.contentHash,packageName:B.packageName,publisher:B.publisher,rowCount:B.resourceCount}}resolveView(e,t){let r=X(e,t);if(!r)throw new Error(`View ${t.publisher}/${t.package_}/${t.name} not found in the catalog.`);let n=M(r,ko);if(n){let s=X(e,n);if(!s)throw new Error(`ViewPackage ${t.name} names rootView ${n.name}, which is not in the catalog.`);return s}return r}readProjections(e,t){let r=[];for(let n of ge(t,Po)){let s=n instanceof D?n:n instanceof j?X(e,n.subject):void 0;if(!s)continue;let i=he(s,bo),a=M(s,Ro);i&&a&&r.push({value:i,as:a})}return r}async reason(e){return new ke({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,t,r){let n=Co(e),s=[],i=new Set;for(let a of r.getInstancesOfClass(t)){if(i.has(a))continue;i.add(a);let l=n.get(a);l&&s.push(l)}return s.sort((a,l)=>{let d=V(P(a)),p=V(P(l));return d<p?-1:d>p?1:0}),s}async passesWhere(e,t,r,n){for(let s of r){let i=await this.evaluateValue(e,t,s,n);if(!Do(i))return!1}return!0}async evaluateValue(e,t,r,n){let s=Ue(r,"view-projection",{catalog:t,depth:0}),i=new Map([["input",n]]);return e.evaluate(s,i)}rowName(e,t){let r=W(e.name)||"row",n=r,s=2;for(;t.has(n);)n=`${r}-${s++}`;return t.add(n),n}};function gt(o){return ve(o)?o.value:Array.isArray(o)?o.map(gt):o}function Eo(o){let e=P(o);if(!e)throw new Error(`Could not derive a publisher from view ${o.namespace}/${o.name}.`);return e.publisher}function ht(o,e,t){let r=xo(o,e,t);if(!r)throw new Error(`Package ${e}/${t} is not in the catalog; it must be importable to materialize a view.`);return r}function xo(o,e,t){let r;for(let n of o){if(!(n instanceof A))continue;let s=P(n);!s||s.publisher!==e||s.package_!==t||!s.version||(!r||q(s.version,r)>0)&&(r=s.version)}return r?R(r):void 0}function Co(o){let e=new Map,t=new Map;for(let r of o){if(!(r instanceof A))continue;let n=P(r);if(!n||!n.version)continue;let s=V(n),i=t.get(s);(!i||q(n.version,i)>0)&&(t.set(s,n.version),e.set(s,r))}return e}function Ao(o,e){let t=he(o,e);return t?[t]:ge(o,e).filter(r=>r instanceof D)}function Do(o){return o===!0?!0:o===!1||o===void 0||o===null?!1:typeof o=="string"?o.length>0:typeof o=="number"?o!==0:ve(o)?o.value.length>0:Array.isArray(o)?o.length>0:!!o}export{ln as AmbiguousReferenceRule,ir as BooleanStatement,wn as CANONICAL_FORM_VERSION,mr as Carrier,fn as ClassDefinitionRule,tn as ClassHierarchyCycleRule,Bt as CompositeKanonakDocumentRepository,ce as CredentialResolver,ie as CredentialStore,st as DEFAULT_CONSENT_BINDING_PARAM,Qt as DefinedKanonak,w as DeviceCertificateStore,Nt as DocumentLocation,br as EdgeType,D as EmbeddedKanonak,Yr as EmbeddedKanonakTypeRule,cr as EmbeddedStatement,G as EntitlementDeniedError,de as EntitlementProducer,It as FileSystemKanonakDocumentRepository,Dr as GitIgnoreFilter,Rr as GraphBuilder,Gt as HttpKanonakDocumentRepository,z as ImportBook,Qr as ImportExistenceRule,Kt as InMemoryKanonakDocumentRepository,Mt as KANONAK_USER_AGENT,Yt as Kanonak,$r as KanonakDocumentPositions,L as KanonakObjectParser,gn as KanonakObjectValidator,O as KanonakParser,er as KanonakUri,Ir as KanonakUriBuilder,Br as KanonakUrlResolver,kr as KanonakVocabulary,lr as ListStatement,tr as LiteralKanonak,Jt as LocalFirstRepository,qt as LockAwareRepository,vn as LookRenderer,hn as MarkdownLinkRule,dr as MarkdownStatement,an as NamespaceImportCycleRule,Gr as NamespacePrefixRule,wr as NodeType,sr as NumberStatement,b as OAuthDiscovery,Cr as OWL_RL_CLASSIFICATION_RULES,pn as ObjectPropertyValueValidationRule,Hr as OntologyValidationError,Ur as OntologyValidationResult,N as PackageBuilder,Zr as PackageHeaderRule,le as ProducerRepository,un as PropertyDomainRule,rn as PropertyHierarchyCycleRule,mn as PropertyKindRangeConsistencyRule,Tr as PropertyMetadata,dn as PropertyRangeReferenceRule,nn as PropertyRangeRequiredRule,qr as PropertyTypeSpecificityRule,Ht as PublisherConfigResolver,zt as PublisherIndex,xr as RDFS_RULES,ke as Reasoner,Ar as ReasoningResult,j as ReferenceKanonak,ar as ReferenceStatement,jt as RepositoryFactory,yn as ReservedNameShadowRule,Jr as ResourceNamingRule,pr as ResourceResolver,Pr as ResourceTypeClassifier,nr as ScalarStatement,K as SessionError,_ as SessionExchange,S as SessionExchangeError,I as SessionManager,$ as SessionStore,rr as Statement,or as StringStatement,on as SubClassOfReferenceRule,sn as SubPropertyOfReferenceRule,A as SubjectKanonak,Xr as SubjectKanonakTypeRequiredRule,Er as TripleStore,ur as TypeResolver,cn as UnresolvedPredicateRule,en as UnresolvedReferenceRule,Wr as ValidationCache,zr as ValidationContext,Fr as ValidationSeverity,aa as VersionOperator,pe as ViewMaterializer,Te as allowAllPolicy,Ut as assertHttpsUrl,Wt as assertPackageIdentity,Zt as buildLocalFirstRepository,bn as buildOntologyModel,Pn as canonicalForm,Pe as canonicalHash,yr as carrierOf,Xt as collectKanonakFiles,q as compareVersions,Ve as computeIntegrity,De as contentAddressedName,Vr as contextTypesOf,dt as createAuthenticatedFetch,H as createDPoPProof,At as createVersion,vr as extractMarkdownLinks,kn as findDerivation,Lr as findInstancesByType,Sr as findMalformedReferences,Kr as findMarkdownLinkAt,Nr as formatKanonakAddress,R as formatVersion,ct as generateDPoPKeyPair,Ot as getGlobalCachePath,Lt as getKanonakUserAgent,Y as hasValidToken,Tt as isCompatibleVersion,Z as isExpired,$t as isMajorCompatible,C as kanonakFetch,je as loadLockFile,fr as makeUriKey,$e as noopMeter,c as normalizeHost,Se as parseKanonakAddress,Dt as parseVersionString,_r as parseWithPositions,_t as pickHighestDocument,jr as propertiesInScope,Sn as resolveDisplayValue,Mr as resolvePropertyStep,W as sanitizeName,Me as saveLockFile,lt as serverSupportsDPoP,ae as sessionNeedsRefresh,Ft as setKanonakFetchRetries,Vt as setKanonakUserAgent,P as subjectUri,Or as superClassChain,hr as tripleKey,V as uriKey,gr as uriTriple,xt as versionOperatorFromChar,fe as versionOperatorToChar,Ct as versionsEqual};
|
|
101
|
+
`:o.certificatePem}function io(o){try{return oo({key:o,format:"jwk"}).export({type:"pkcs8",format:"pem"})}catch(e){throw new S(`The device key is not an exportable software private key, so it cannot present mTLS in software (a future hardware key provider would do the handshake itself): ${e.message}`)}}var ao=o=>new Promise((e,t)=>{let r=new URL(o.url),n=it.request({method:"POST",hostname:r.hostname,port:r.port||443,path:r.pathname+r.search,cert:o.certPem,key:o.keyPem,headers:{"Content-Type":o.contentType,"Content-Length":Buffer.byteLength(o.body),Accept:"application/json"},timeout:3e4},s=>{let i=[];s.on("data",a=>i.push(a)),s.on("end",()=>e({status:s.statusCode??0,body:Buffer.concat(i).toString("utf-8")}))});n.on("error",t),n.on("timeout",()=>n.destroy(new Error("mTLS request timed out"))),n.write(o.body),n.end()});var I=class extends Error{},N=class{discovery;deviceStore;sessionStore;exchange;constructor(e={}){this.discovery=e.discovery??new b,this.deviceStore=e.deviceStore??new w,this.sessionStore=e.sessionStore??new _,this.exchange=e.exchange??new K}async acquire(e){let t=l(e),r=await this.sessionEndpoint(e);if(!r)throw new I(`'${t}' does not advertise a session endpoint \u2014 it issues no scoped sessions (public registries need no credential).`);let n=await this.deviceStore.get(e);if(!n)throw new I(`No device certificate enrolled for '${t}'. Run 'kanonak device enroll ${e}' first.`);let s=await this.exchange.exchange(r,n),i={token:s.token,tokenType:s.tokenType,expiresAt:s.expiresAt,scope:s.scope};return await this.sessionStore.store(t,i),i}async getValidSession(e,t={}){let r=l(e),n=await this.sessionStore.get(r);return!t.forceRefresh&&n&&!ce(n)?n:!await this.sessionEndpoint(e)||!await this.deviceStore.get(e)?null:this.acquire(e)}async clear(e){await this.sessionStore.remove(l(e))}async sessionEndpoint(e){return(await this.discovery.discover(e))?.sessionEndpoint??null}};var le=class{discovery;sessions;devices;constructor(e={}){this.discovery=e.discovery??new b,this.sessions=e.sessionManager??new N({discovery:this.discovery}),this.devices=e.deviceStore??new w}async resolve(e,t={}){let r=await this.discovery.discoverProtectedResource(e);if(!r||r.length===0)return null;let n=r.map(co).filter(a=>a!==void 0);for(let a of n){let c=await this.sessionFor(a,t.forceRefresh);if(c)return c}let i=(await this.devices.list()).map(l).filter(a=>!n.includes(a));if(i.length===0)return null;for(let a of n){let c=(await this.discovery.discover(a))?.sessionEndpoint;if(c)for(let d of i){if((await this.discovery.discover(d))?.sessionEndpoint!==c)continue;let C=await this.sessionFor(d,t.forceRefresh);if(C)return C}}return null}async sessionFor(e,t=!1){let r=await this.sessions.getValidSession(e,{forceRefresh:t});return r?{authority:e,token:r.token,expiresAt:r.expiresAt,scope:r.scope}:null}};function co(o){try{return new URL(o).host}catch{return}}import{createHash as lo,createPrivateKey as po,generateKeyPairSync as uo,randomUUID as mo,sign as fo}from"crypto";function ct(){let{publicKey:o,privateKey:e}=uo("ec",{namedCurve:"P-256"});return{publicKey:o.export({format:"jwk"}),privateKey:e.export({format:"jwk"})}}function z(o,e,t,r,n,s){let i={alg:"ES256",typ:"dpop+jwt",jwk:{kty:e.kty,crv:e.crv,x:e.x,y:e.y}},a={jti:mo(),htm:t.toUpperCase(),htu:r,iat:Math.floor(Date.now()/1e3)};return n&&(a.ath=lo("sha256").update(n).digest("base64url")),s&&(a.nonce=s),yo(i,a,o)}function lt(o){return!o||o.length===0?!1:o.some(e=>e.toUpperCase()==="ES256")}function yo(o,e,t){let r=at(JSON.stringify(o)),n=at(JSON.stringify(e)),s=`${r}.${n}`,i=po({key:t,format:"jwk"}),c=fo("SHA256",Buffer.from(s),{key:i,dsaEncoding:"ieee-p1363"}).toString("base64url");return`${s}.${c}`}function at(o){return Buffer.from(o,"utf-8").toString("base64url")}function dt(o){let e=new Map;return async(t,r,n="GET")=>{if(!o)return A(t,{method:n});let s=await o.getCredential(r);if(!s?.accessToken)return A(t,{method:n});Y(s)&&console.warn(` Warning: Access token for '${r}' is expired. Run 'kanonak login ${r}' to re-authenticate.`);let i={};if(s.dpopKeyPair){let c=e.get(r);try{let d=z(s.dpopKeyPair.privateKey,s.dpopKeyPair.publicKey,n,t,s.accessToken,c);i.Authorization=`DPoP ${s.accessToken}`,i.DPoP=d}catch(d){let p=d instanceof Error?d.message:String(d);console.error(` Error: Failed to create DPoP proof for '${r}': ${p}
|
|
102
|
+
The stored key pair may be corrupted. Run 'kanonak login ${r}' to re-authenticate.`),i.Authorization=`Bearer ${s.accessToken}`}}else i.Authorization=`Bearer ${s.accessToken}`;let a=await A(t,{method:n,headers:i});if(a.status===401&&s.dpopKeyPair){let c=a.headers.get("DPoP-Nonce");if(c){e.set(r,c);try{let d=z(s.dpopKeyPair.privateKey,s.dpopKeyPair.publicKey,n,t,s.accessToken,c);i.DPoP=d,a=await A(t,{method:n,headers:i})}catch{}}}return a}}import*as Ae from"js-yaml";import{VersionOperator as pt}from"@kanonak-protocol/types/document/models/enums";var ho="0.0.0",B=class{constructor(e,t=new j,r){this.repository=e;this.parser=t;this.objectParser=r??new U(this.parser)}repository;parser;objectParser;imports(){return new W}serializeValue(e,t){return ft(e,t)}async buildContentAddressed(e){let t=e.book.toImports(),r=await this.hashBody(e.publisher,t,e.body),n=De(r),s={type:"EphemeralPackage",publisher:e.publisher,imports:t};e.contentHashProperty&&(s[e.contentHashProperty]=r),Object.assign(s,e.header??{}),s.imports=t;let i={[n]:s,...e.body},a=this.dump(i);return{yaml:a,byteCount:mt(a),contentHash:r,packageName:n,publisher:e.publisher,resourceCount:Object.keys(e.body).length}}async buildNamed(e){let t=e.book.toImports(),r={type:e.type??"Package",publisher:e.publisher,version:e.version,imports:t},n;e.contentHashProperty&&(n=await this.hashBody(e.publisher,t,e.body),r[e.contentHashProperty]=n),Object.assign(r,e.header??{}),r.imports=t;let s={[e.name]:r,...e.body},i=this.dump(s),a={yaml:i,byteCount:mt(i),packageName:e.name,publisher:e.publisher,resourceCount:Object.keys(e.body).length};return n!==void 0&&(a.contentHash=n),a}dump(e){return Ae.dump(e,{lineWidth:-1})}async hashBody(e,t,r){let n={[ut]:{type:"EphemeralPackage",publisher:e,imports:t},...r},s=this.parser.parse(Ae.dump(n,{lineWidth:-1})),i=s.metadata.namespace_?.toString(),c=(await this.objectParser.parseKanonaks(new Oe(s,this.repository))).filter(d=>d instanceof D&&d.namespace===i&&d.name!==ut);for(let d of c)d.namespace="ephemeral";return Pe(c)}},ut="__pkgbuilder_probe__";function mt(o){return new TextEncoder().encode(o).length}function De(o){let e="sha256:",t=o.startsWith(e)?e.length:0;return`q-${o.slice(t,t+16)}`}var W=class{byKey=new Map;aliases=new Set;ensure(e,t,r,n,s=pt.Major){let i=`${e}/${t}@${r}`,a=this.byKey.get(i);if(a)return a.alias;let c=this.uniqueAlias(n);return this.byKey.set(i,{publisher:e,package_:t,version:r,alias:c,match:s}),c}ref(e){if(!e.version||typeof e.version.major!="number")throw new Error(`Cannot serialize a reference to ${e.publisher}/${e.package_}/${e.name} without a version.`);return`${this.ensure(e.publisher,e.package_,R(e.version),e.package_)}.${e.name}`}refLatest(e,t,r,n){return`${this.ensure(e,t,ho,n??t,pt.Any)}.${r}`}toImports(){let e=new Map;for(let r of this.byKey.values()){let n=e.get(r.publisher)??[];n.push(r),e.set(r.publisher,n)}return[...e.keys()].sort().map(r=>({publisher:r,packages:e.get(r).sort((n,s)=>n.package_<s.package_?-1:1).map(n=>({package:n.package_,match:ye(n.match),version:n.version,alias:n.alias}))}))}uniqueAlias(e){let t=G(e)||"pkg",r=t,n=2;for(;this.aliases.has(r);)r=`${t}${n++}`;return this.aliases.add(r),r}};function ft(o,e){if(o!=null){if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o;if(o instanceof M)return e.ref(o.subject);if(Array.isArray(o)){let t=o.map(r=>ft(r,e)).filter(r=>r!==void 0);return t.length>0?t:void 0}if(o instanceof T)throw new Error("Embedded values are not yet supported by PackageBuilder. Produce a literal or a reference, or compose the embedded shape into the output class.");if(go(o))throw new Error(`Value produced a bare URI without a version (${o.publisher}/${o.package_}/${o.name}); cannot serialize it as a reference.`)}}function G(o){return o.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function go(o){return typeof o=="object"&&o!==null&&typeof o.publisher=="string"&&typeof o.package_=="string"&&typeof o.name=="string"}var de=class{constructor(e){this.producers=e}producers;produced=new Map;producerFor(e,t){return this.producers.find(r=>r.canProduce(e,t))}async produceCached(e,t,r,n){let s=`${t}/${r}@${R(n)}`,i=this.produced.get(s);if(i)return i;let{document:a}=await e.produce(t,r,n);return this.produced.set(s,a),a}async getHighestCompatibleVersionAsync(e,t){let r=this.producerFor(e,t.packageName);if(!r)return null;let n={operator:t.versionOperator,version:t.version},s=await r.resolveVersion(e,t.packageName,n);return s?this.produceCached(r,e,t.packageName,s):null}async getDocumentAsync(e){let t;try{t=Se(e)}catch{return null}if(t.kind!=="package"||!t.version)return null;let r=this.producerFor(t.publisher,t.package_);return r?this.produceCached(r,t.publisher,t.package_,t.version):null}async getDocumentsByNamespaceAsync(e,t){return Array.from(this.produced.values()).filter(r=>{let n=r.metadata.namespace_;return n!=null&&n.publisher===e&&n.package_===t})}async getAllDocumentsAsync(){return Array.from(this.produced.values())}async saveDocumentAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async deleteDocumentAsync(e){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async clearNamespaceAsync(e,t){throw new Error("ProducerRepository is read-only: a producer is a source, not a store.")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(e){return null}async getDocumentUriAsync(e){return null}};var Te={async authorize(){return{allowed:!0}}},$e={async record(){}},J=class extends Error{constructor(t,r){let n=`${t.publisher}/${t.package_}${t.version?`@${t.version.major}.${t.version.minor}.${t.version.patch}`:""}`;super(`Not entitled to produce ${n}${r?`: ${r}`:""}`);this.address=t;this.reason=r;this.name="EntitlementDeniedError"}address;reason},pe=class{inner;ctx;policy;meter;constructor(e,t,r=Te,n=$e){this.inner=e,this.ctx=t,this.policy=r,this.meter=n}canProduce(e,t){return this.inner.canProduce(e,t)}async resolveVersion(e,t,r){return await this.assertAllowed({publisher:e,package_:t,version:r.version}),this.inner.resolveVersion(e,t,r)}async produce(e,t,r){let n={publisher:e,package_:t,version:r};await this.assertAllowed(n);let s=await this.inner.produce(e,t,r);return await this.meter.record(this.ctx,n,s),s}async assertAllowed(e){let t=await this.policy.authorize(this.ctx,e);if(!t.allowed)throw new J(e,t.reason)}};var u="kanonak.org",v="view",yt="core-kanonak",ko={publisher:u,package_:v,name:"rootView"},So={publisher:u,package_:v,name:"bind"},vo={publisher:u,package_:v,name:"produces"},Po={publisher:u,package_:v,name:"projections"},wo={publisher:u,package_:v,name:"where"},bo={publisher:u,package_:v,name:"value"},Ro={publisher:u,package_:v,name:"as"},ue=class{constructor(e,t=new j){this.repository=e;this.parser=t;this.objectParser=new U(this.parser),this.builder=new B(this.repository,this.parser,this.objectParser)}repository;parser;objectParser;builder;async materialize(e,t={}){let r=await this.objectParser.parseKanonaks(this.repository),n=this.resolveView(r,e),s=V(n,So);if(!s)throw new Error(`View ${n.namespace}/${n.name} declares no view.bind; cannot materialize.`);let i=V(n,vo);if(!i)throw new Error(`View ${n.namespace}/${n.name} is a selection view (no view.produces). In-graph materialization of selection views is not yet supported \u2014 declare a view.produces output class to reshape the result.`);let a=Eo(n),c=ht(r,u,yt),d=ht(r,u,v),p=this.builder.imports(),C=p.ensure(u,yt,c,"ck"),kt=p.ensure(u,v,d,"v"),St=p.ref(i),vt=new Fe(this.repository,this.parser,this.objectParser),_e=new Le(vt,r),Pt=this.readProjections(r,n),wt=Ao(n,wo),bt=this.findInstances(r,s,await this.reason(t)),Ke={},Rt=new Set;for(let q of bt){if(!await this.passesWhere(_e,r,wt,q))continue;let fe={type:St};for(let Ne of Pt){let Et=await this.evaluateValue(_e,r,Ne.value,q),Be=this.builder.serializeValue(gt(Et),p);Be!==void 0&&(fe[p.ref(Ne.as)]=Be)}let Ie=P(q);Ie&&(fe[`${kt}.derivedFrom`]=p.ref(Ie)),Ke[this.rowName(q,Rt)]=fe}let me={};t.resolvedAt&&(me[`${C}.resolvedAt`]=t.resolvedAt),t.invocationId&&(me[`${C}.id`]=t.invocationId);let O=await this.builder.buildContentAddressed({publisher:a,book:p,body:Ke,contentHashProperty:`${C}.contentHash`,header:me});return{yaml:O.yaml,contentHash:O.contentHash,packageName:O.packageName,publisher:O.publisher,rowCount:O.resourceCount}}resolveView(e,t){let r=Z(e,t);if(!r)throw new Error(`View ${t.publisher}/${t.package_}/${t.name} not found in the catalog.`);let n=V(r,ko);if(n){let s=Z(e,n);if(!s)throw new Error(`ViewPackage ${t.name} names rootView ${n.name}, which is not in the catalog.`);return s}return r}readProjections(e,t){let r=[];for(let n of ge(t,Po)){let s=n instanceof T?n:n instanceof M?Z(e,n.subject):void 0;if(!s)continue;let i=he(s,bo),a=V(s,Ro);i&&a&&r.push({value:i,as:a})}return r}async reason(e){return new ke({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,t,r){let n=Co(e),s=[],i=new Set;for(let a of r.getInstancesOfClass(t)){if(i.has(a))continue;i.add(a);let c=n.get(a);c&&s.push(c)}return s.sort((a,c)=>{let d=L(P(a)),p=L(P(c));return d<p?-1:d>p?1:0}),s}async passesWhere(e,t,r,n){for(let s of r){let i=await this.evaluateValue(e,t,s,n);if(!Do(i))return!1}return!0}async evaluateValue(e,t,r,n){let s=Ue(r,"view-projection",{catalog:t,depth:0}),i=new Map([["input",n]]);return e.evaluate(s,i)}rowName(e,t){let r=G(e.name)||"row",n=r,s=2;for(;t.has(n);)n=`${r}-${s++}`;return t.add(n),n}};function gt(o){return ve(o)?o.value:Array.isArray(o)?o.map(gt):o}function Eo(o){let e=P(o);if(!e)throw new Error(`Could not derive a publisher from view ${o.namespace}/${o.name}.`);return e.publisher}function ht(o,e,t){let r=xo(o,e,t);if(!r)throw new Error(`Package ${e}/${t} is not in the catalog; it must be importable to materialize a view.`);return r}function xo(o,e,t){let r;for(let n of o){if(!(n instanceof D))continue;let s=P(n);!s||s.publisher!==e||s.package_!==t||!s.version||(!r||X(s.version,r)>0)&&(r=s.version)}return r?R(r):void 0}function Co(o){let e=new Map,t=new Map;for(let r of o){if(!(r instanceof D))continue;let n=P(r);if(!n||!n.version)continue;let s=L(n),i=t.get(s);(!i||X(n.version,i)>0)&&(t.set(s,n.version),e.set(s,r))}return e}function Ao(o,e){let t=he(o,e);return t?[t]:ge(o,e).filter(r=>r instanceof T)}function Do(o){return o===!0?!0:o===!1||o===void 0||o===null?!1:typeof o=="string"?o.length>0:typeof o=="number"?o!==0:ve(o)?o.value.length>0:Array.isArray(o)?o.length>0:!!o}export{ln as AmbiguousReferenceRule,ir as BooleanStatement,wn as CANONICAL_FORM_VERSION,mr as Carrier,yn as ClassDefinitionRule,tn as ClassHierarchyCycleRule,Bt as CompositeKanonakDocumentRepository,le as CredentialResolver,ae as CredentialStore,st as DEFAULT_CONSENT_BINDING_PARAM,Qt as DefinedKanonak,w as DeviceCertificateStore,Nt as DocumentLocation,br as EdgeType,T as EmbeddedKanonak,Yr as EmbeddedKanonakTypeRule,cr as EmbeddedStatement,J as EntitlementDeniedError,pe as EntitlementProducer,It as FileSystemKanonakDocumentRepository,Dr as GitIgnoreFilter,Rr as GraphBuilder,Gt as HttpKanonakDocumentRepository,W as ImportBook,Qr as ImportExistenceRule,Kt as InMemoryKanonakDocumentRepository,Mt as KANONAK_USER_AGENT,Yt as Kanonak,$r as KanonakDocumentPositions,U as KanonakObjectParser,gn as KanonakObjectValidator,j as KanonakParser,er as KanonakUri,Ir as KanonakUriBuilder,Br as KanonakUrlResolver,kr as KanonakVocabulary,lr as ListStatement,tr as LiteralKanonak,Jt as LocalFirstRepository,qt as LockAwareRepository,vn as LookRenderer,hn as MarkdownLinkRule,dr as MarkdownStatement,an as NamespaceImportCycleRule,Gr as NamespacePrefixRule,wr as NodeType,sr as NumberStatement,b as OAuthDiscovery,Cr as OWL_RL_CLASSIFICATION_RULES,pn as ObjectPropertyValueValidationRule,Hr as OntologyValidationError,Ur as OntologyValidationResult,B as PackageBuilder,Zr as PackageHeaderRule,de as ProducerRepository,un as PropertyDomainRule,rn as PropertyHierarchyCycleRule,mn as PropertyKindRangeConsistencyRule,Tr as PropertyMetadata,dn as PropertyRangeReferenceRule,nn as PropertyRangeRequiredRule,qr as PropertyTypeSpecificityRule,Ht as PublisherConfigResolver,zt as PublisherIndex,xr as RDFS_RULES,ke as Reasoner,Ar as ReasoningResult,M as ReferenceKanonak,ar as ReferenceStatement,jt as RepositoryFactory,fn as ReservedNameShadowRule,Jr as ResourceNamingRule,pr as ResourceResolver,Pr as ResourceTypeClassifier,nr as ScalarStatement,I as SessionError,K as SessionExchange,S as SessionExchangeError,N as SessionManager,_ as SessionStore,rr as Statement,or as StringStatement,on as SubClassOfReferenceRule,sn as SubPropertyOfReferenceRule,D as SubjectKanonak,Xr as SubjectKanonakTypeRequiredRule,Er as TripleStore,ur as TypeResolver,cn as UnresolvedPredicateRule,en as UnresolvedReferenceRule,Wr as ValidationCache,zr as ValidationContext,Fr as ValidationSeverity,aa as VersionOperator,ue as ViewMaterializer,Te as allowAllPolicy,Ut as assertHttpsUrl,Wt as assertPackageIdentity,Zt as buildLocalFirstRepository,bn as buildOntologyModel,Pn as canonicalForm,Pe as canonicalHash,fr as carrierOf,Xt as collectKanonakFiles,X as compareVersions,Ve as computeIntegrity,De as contentAddressedName,Vr as contextTypesOf,dt as createAuthenticatedFetch,z as createDPoPProof,At as createVersion,vr as extractMarkdownLinks,kn as findDerivation,Lr as findInstancesByType,Sr as findMalformedReferences,Kr as findMarkdownLinkAt,Nr as formatKanonakAddress,R as formatVersion,ct as generateDPoPKeyPair,Ot as getGlobalCachePath,Lt as getKanonakUserAgent,Q as hasValidToken,Tt as isCompatibleVersion,Y as isExpired,$t as isMajorCompatible,A as kanonakFetch,je as loadLockFile,yr as makeUriKey,$e as noopMeter,l as normalizeHost,Se as parseKanonakAddress,Dt as parseVersionString,_r as parseWithPositions,_t as pickHighestDocument,jr as propertiesInScope,Sn as resolveDisplayValue,Mr as resolvePropertyStep,G as sanitizeName,Me as saveLockFile,lt as serverSupportsDPoP,ce as sessionNeedsRefresh,Ft as setKanonakFetchRetries,Vt as setKanonakUserAgent,P as subjectUri,Or as superClassChain,hr as tripleKey,L as uriKey,gr as uriTriple,xt as versionOperatorFromChar,ye as versionOperatorToChar,Ct as versionsEqual};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanonak-protocol/sdk",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "TypeScript SDK for the Kanonak Protocol — parse, resolve, validate, reason over, and render .kan.yml packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
],
|
|
127
127
|
"dependencies": {
|
|
128
128
|
"@kanonak-protocol/canonical": "^0.1.1",
|
|
129
|
-
"@kanonak-protocol/types": "^5.
|
|
129
|
+
"@kanonak-protocol/types": "^5.9.0",
|
|
130
130
|
"ignore": "^7.0.5",
|
|
131
131
|
"js-yaml": "^4.1.0",
|
|
132
132
|
"yaml": "^2.7.0"
|