@kanonak-protocol/sdk 4.12.0 → 4.13.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.
@@ -1,14 +1,23 @@
1
1
  /**
2
- * Pluggable credential storage backend interface.
3
- * Implementations store OAuth credentials per publisher domain
4
- * in platform-specific secure stores.
2
+ * Pluggable secure-storage backend: JSON values of type `T` keyed by a
3
+ * normalized host, in a platform-specific secure store (OS keychain, encrypted
4
+ * file, enterprise vault). The same backend implementations serve different
5
+ * record types under different namespaces — OAuth credentials
6
+ * ({@link StoredCredential}) and device enrollments — so the storage mechanism
7
+ * is written once and reused.
5
8
  */
6
- export interface CredentialBackend {
7
- get(publisher: string): Promise<StoredCredential | null>;
8
- store(publisher: string, credential: StoredCredential): Promise<void>;
9
+ export interface SecretBackend<T> {
10
+ get(publisher: string): Promise<T | null>;
11
+ store(publisher: string, value: T): Promise<void>;
9
12
  remove(publisher: string): Promise<void>;
10
13
  list(): Promise<string[]>;
11
14
  }
15
+ /**
16
+ * The OAuth credential storage backend — a {@link SecretBackend} whose records
17
+ * are {@link StoredCredential}. Kept as a named alias so existing consumers and
18
+ * the `CredentialStore` are unchanged.
19
+ */
20
+ export type CredentialBackend = SecretBackend<StoredCredential>;
12
21
  /**
13
22
  * OAuth credential stored per publisher host.
14
23
  * Matches the OAuthCredentialStore types from @kanonak-protocol/types.
@@ -1,4 +1,4 @@
1
- import type { CredentialBackend, StoredCredential } from './CredentialBackend.js';
1
+ import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
2
2
  /**
3
3
  * External credential helper backend.
4
4
  * Delegates to an enterprise-configured binary using a stdin/stdout JSON protocol.
@@ -6,11 +6,11 @@ import type { CredentialBackend, StoredCredential } from './CredentialBackend.js
6
6
  * Configure in ~/.kanonak/config.json:
7
7
  * { "credentialHelper": "/usr/local/bin/kanonak-credential-vault" }
8
8
  */
9
- export declare class CredentialHelperBackend implements CredentialBackend {
9
+ export declare class CredentialHelperBackend<T = StoredCredential> implements SecretBackend<T> {
10
10
  private readonly helperPath;
11
11
  constructor(helperPath: string);
12
- get(publisher: string): Promise<StoredCredential | null>;
13
- store(publisher: string, credential: StoredCredential): Promise<void>;
12
+ get(publisher: string): Promise<T | null>;
13
+ store(publisher: string, value: T): Promise<void>;
14
14
  remove(publisher: string): Promise<void>;
15
15
  list(): Promise<string[]>;
16
16
  private runHelper;
@@ -0,0 +1,52 @@
1
+ import type { SecretBackend } from './CredentialBackend.js';
2
+ import { normalizeHost } from './CredentialBackend.js';
3
+ /**
4
+ * A device certificate enrollment, persisted per registry host (issue #67).
5
+ *
6
+ * The record holds the device-held key material, the CA-signed certificate, and
7
+ * the consent context. In v1 the key is a software key (its private JWK lives in
8
+ * `keyMaterial`); a future hardware {@link KeyProvider} stores an opaque handle
9
+ * here instead, so the secure store never holds an exportable key. Either way the
10
+ * record is opaque JSON to the storage backend.
11
+ */
12
+ export interface DeviceEnrollmentRecord {
13
+ /** Software provider: the private key JWK. Hardware provider: an opaque key handle. */
14
+ keyMaterial: Record<string, unknown>;
15
+ /** RFC 7638 JWK SHA-256 thumbprint of the device public key — the consent-bound identity. */
16
+ thumbprint: string;
17
+ /** The CA-signed leaf certificate (PEM). */
18
+ certificatePem: string;
19
+ /** The issuing chain (PEM, possibly empty). */
20
+ chainPem: string;
21
+ /** ISO timestamp the certificate was issued/installed. */
22
+ issuedAt: string;
23
+ /** ISO timestamp the certificate expires, or null if unknown. */
24
+ expiresAt: string | null;
25
+ /** The scopes consented at enrollment. */
26
+ scopes: string[];
27
+ /** A human-facing device label shown on the consent screen. */
28
+ deviceName?: string;
29
+ }
30
+ /**
31
+ * Persists {@link DeviceEnrollmentRecord}s in the same platform-secure stores as
32
+ * OAuth credentials, but under a separate `kanonak-device` namespace so the two
33
+ * never collide (separate Keychain service / Credential Manager target prefix /
34
+ * Secret Service attribute / encrypted file). Mirrors {@link CredentialStore}'s
35
+ * backend selection; the external credential-helper backend is intentionally not
36
+ * used for device certs in v1 (device enrollment is a first-party flow).
37
+ *
38
+ * This is a Node-only module (it reaches OS keystores) and is deliberately not
39
+ * exported from the SDK browser entry.
40
+ */
41
+ export declare class DeviceCertificateStore {
42
+ private backend;
43
+ private backendReady;
44
+ getBackend(): Promise<SecretBackend<DeviceEnrollmentRecord>>;
45
+ get(host: string): Promise<DeviceEnrollmentRecord | null>;
46
+ store(host: string, record: DeviceEnrollmentRecord): Promise<void>;
47
+ remove(host: string): Promise<void>;
48
+ list(): Promise<string[]>;
49
+ private resolveBackend;
50
+ }
51
+ /** Re-exported for callers that namespace device records themselves. */
52
+ export { normalizeHost };
@@ -1,15 +1,19 @@
1
- import type { CredentialBackend, StoredCredential } from './CredentialBackend.js';
1
+ import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
2
2
  /**
3
- * Encrypted file credential backend.
3
+ * Encrypted file secret backend.
4
4
  * Fallback for headless Linux, containers, and CI environments
5
- * where no OS keyring is available.
5
+ * where no OS keyring is available. The secrets file is namespaced (OAuth
6
+ * credentials in `credentials.enc`, device enrollments in `device-credentials.enc`)
7
+ * so the two stores never collide; both are sealed with the same per-user key.
6
8
  *
7
9
  * - Key: ~/.config/kanonak/keyring.key (random 32 bytes, mode 0600)
8
- * - Secrets: ~/.config/kanonak/credentials.enc (AES-256-GCM encrypted JSON)
10
+ * - Secrets: a per-namespace AES-256-GCM encrypted JSON file
9
11
  */
10
- export declare class EncryptedFileBackend implements CredentialBackend {
11
- get(publisher: string): Promise<StoredCredential | null>;
12
- store(publisher: string, credential: StoredCredential): Promise<void>;
12
+ export declare class EncryptedFileBackend<T = StoredCredential> implements SecretBackend<T> {
13
+ private readonly secretsFile;
14
+ constructor(secretsFile?: string);
15
+ get(publisher: string): Promise<T | null>;
16
+ store(publisher: string, value: T): Promise<void>;
13
17
  remove(publisher: string): Promise<void>;
14
18
  list(): Promise<string[]>;
15
19
  private loadStore;
@@ -1,11 +1,15 @@
1
- import type { CredentialBackend, StoredCredential } from './CredentialBackend.js';
1
+ import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
2
2
  /**
3
- * macOS Keychain credential backend.
4
- * Stores credentials via the `security` CLI tool (no native modules).
3
+ * macOS Keychain secret backend.
4
+ * Stores records via the `security` CLI tool (no native modules). The Keychain
5
+ * `service` namespaces the store, so OAuth credentials (`kanonak`) and device
6
+ * enrollments (`kanonak-device`) live side by side without colliding.
5
7
  */
6
- export declare class KeychainBackend implements CredentialBackend {
7
- get(publisher: string): Promise<StoredCredential | null>;
8
- store(publisher: string, credential: StoredCredential): Promise<void>;
8
+ export declare class KeychainBackend<T = StoredCredential> implements SecretBackend<T> {
9
+ private readonly service;
10
+ constructor(service?: string);
11
+ get(publisher: string): Promise<T | null>;
12
+ store(publisher: string, value: T): Promise<void>;
9
13
  remove(publisher: string): Promise<void>;
10
14
  list(): Promise<string[]>;
11
15
  }
@@ -1,19 +1,21 @@
1
- import type { CredentialBackend, StoredCredential } from './CredentialBackend.js';
1
+ import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
2
2
  /**
3
3
  * Linux Secret Service backend (GNOME Keyring / KDE Wallet).
4
4
  * Uses the `secret-tool` CLI from libsecret-tools.
5
5
  *
6
- * Each publisher's credential is stored with attributes:
7
- * service = "kanonak"
6
+ * Each record is stored with attributes:
7
+ * service = the namespace ("kanonak" for OAuth, "kanonak-device" for device certs)
8
8
  * publisher = normalized publisher host
9
9
  *
10
10
  * All interactions use execFile (no shell) to prevent command injection.
11
11
  * The store() method uses spawn with stdin piping since secret-tool
12
12
  * reads the secret value from stdin.
13
13
  */
14
- export declare class SecretServiceBackend implements CredentialBackend {
15
- get(publisher: string): Promise<StoredCredential | null>;
16
- store(publisher: string, credential: StoredCredential): Promise<void>;
14
+ export declare class SecretServiceBackend<T = StoredCredential> implements SecretBackend<T> {
15
+ private readonly service;
16
+ constructor(service?: string);
17
+ get(publisher: string): Promise<T | null>;
18
+ store(publisher: string, value: T): Promise<void>;
17
19
  remove(publisher: string): Promise<void>;
18
20
  list(): Promise<string[]>;
19
21
  }
@@ -1,19 +1,23 @@
1
- import type { CredentialBackend, StoredCredential } from './CredentialBackend.js';
1
+ import type { SecretBackend, StoredCredential } from './CredentialBackend.js';
2
2
  /**
3
3
  * Windows Credential Manager backend.
4
4
  * Uses PowerShell P/Invoke to Advapi32.dll for CredRead/CredWrite/CredDelete.
5
5
  * cmdkey cannot read passwords back, so P/Invoke is required.
6
6
  *
7
- * Each publisher's credential is stored as a generic credential with:
8
- * target = "kanonak:{normalized_publisher}"
9
- * credential blob = JSON-serialized StoredCredential (UTF-16)
7
+ * Each record is stored as a generic credential with:
8
+ * target = "{prefix}{normalized_publisher}"
9
+ * credential blob = JSON-serialized record (UTF-16)
10
10
  *
11
- * Data is passed to PowerShell via stdin to prevent injection attacks.
12
- * No user-supplied values are interpolated into PowerShell code.
11
+ * The `target` prefix namespaces the store, so OAuth credentials (`kanonak:`)
12
+ * and device enrollments (`kanonak-device:`) do not collide. Data is passed to
13
+ * PowerShell via stdin to prevent injection attacks; no user-supplied values
14
+ * are interpolated into PowerShell code.
13
15
  */
14
- export declare class WinCredBackend implements CredentialBackend {
15
- get(publisher: string): Promise<StoredCredential | null>;
16
- store(publisher: string, credential: StoredCredential): Promise<void>;
16
+ export declare class WinCredBackend<T = StoredCredential> implements SecretBackend<T> {
17
+ private readonly targetPrefix;
18
+ constructor(targetPrefix?: string);
19
+ get(publisher: string): Promise<T | null>;
20
+ store(publisher: string, value: T): Promise<void>;
17
21
  remove(publisher: string): Promise<void>;
18
22
  list(): Promise<string[]>;
19
23
  }
@@ -1,6 +1,8 @@
1
- export type { CredentialBackend, StoredCredential, DPoPKeyPair } from './CredentialBackend.js';
1
+ export type { SecretBackend, CredentialBackend, StoredCredential, DPoPKeyPair } from './CredentialBackend.js';
2
2
  export { isExpired, hasValidToken, normalizeHost } from './CredentialBackend.js';
3
3
  export { CredentialStore } from './CredentialStore.js';
4
+ export { DeviceCertificateStore } from './DeviceCertificateStore.js';
5
+ export type { DeviceEnrollmentRecord } from './DeviceCertificateStore.js';
4
6
  export type { AuthenticatedFetchFn } from './AuthenticatedFetch.js';
5
7
  export { createAuthenticatedFetch } from './AuthenticatedFetch.js';
6
8
  export { generateDPoPKeyPair, createDPoPProof, serverSupportsDPoP } from './DPoP.js';
package/dist/browser.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as we,b as ke,c as he,d as E,e as _,f as d,g as tr}from"./chunk-U7LVFPEO.js";import{a as rr}from"./chunk-VWS25JH4.js";import"./chunk-QHABFCRC.js";import{a as F,b as W,c as G,d as w,f as X,g as Q,h as Y}from"./chunk-JYBKSBB5.js";import{a as q}from"./chunk-4NO7MHS7.js";import{a as Ke,b as be,c as xe}from"./chunk-RGOBWOBB.js";import{a as Se,b as Re}from"./chunk-PEUTCG3B.js";import"./chunk-PEJALHXK.js";import"./chunk-SC5M74NM.js";import{A as Xe,B as Qe,C as Ye,D as Ze,M as er,a as De,b as Be,c as Ce,d as Ee,f as _e,g as je,h as ve,i as Ae,k as Te,l as Ie,m as Oe,n as Ue,o as Ve,p as $e,q as Me,r as Ne,s as ze,t as Je,u as He,v as qe,w as Le,x as Fe,y as We,z as Ge}from"./chunk-UBBZWWRB.js";import"./chunk-SHDHMKMJ.js";import{a as te,c as ye,h as me}from"./chunk-BKVPSPG4.js";import{a as L}from"./chunk-NJ3AZYQD.js";import{a as Pe}from"./chunk-IEOSSSB5.js";import"./chunk-7TKJHKC2.js";import{b as ge,c as fe}from"./chunk-7HRKWTBB.js";import{a as Z,b as ee,c as re,d as oe,e as se,f as ie,g as ae,h as ce,i as le,j as ue,k as de,l as pe}from"./chunk-4UT2CLAT.js";import{a as ne}from"./chunk-FUUTGGJS.js";import{c as U,d as V,e as $,f as M,g as N,h as z,i as J,j as H}from"./chunk-2ACBWC7K.js";var j="kanonak-credentials",u="credentials",nr=1,f=class{async get(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readonly"),i=s.objectStore(u).get(e);i.onsuccess=()=>o(i.result??null),i.onerror=()=>a(new Error(`IndexedDB read failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async store(r,e){let t=d(r),o=await h();return new Promise((a,s)=>{let l=o.transaction(u,"readwrite"),c=l.objectStore(u).put(e,t);c.onsuccess=()=>a(),c.onerror=()=>s(new Error(`IndexedDB write failed for '${t}': ${c.error?.message}`)),l.oncomplete=()=>o.close()})}async remove(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readwrite"),i=s.objectStore(u).delete(e);i.onsuccess=()=>o(),i.onerror=()=>a(new Error(`IndexedDB delete failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async list(){let r=await h();return new Promise((e,t)=>{let o=r.transaction(u,"readonly"),s=o.objectStore(u).getAllKeys();s.onsuccess=()=>e(s.result??[]),s.onerror=()=>t(new Error(`IndexedDB list failed: ${s.error?.message}`)),o.oncomplete=()=>r.close()})}};function h(){return new Promise((n,r)=>{let e=indexedDB.open(j,nr);e.onupgradeneeded=()=>{let t=e.result;t.objectStoreNames.contains(u)||t.createObjectStore(u)},e.onsuccess=()=>n(e.result),e.onerror=()=>r(new Error(`Failed to open IndexedDB '${j}': ${e.error?.message}
1
+ import{a as we,b as ke,c as he,d as E,e as _,f as d,g as tr}from"./chunk-NUXUITUC.js";import{a as rr}from"./chunk-VWS25JH4.js";import"./chunk-QHABFCRC.js";import{a as F,b as W,c as G,d as w,f as X,g as Q,h as Y}from"./chunk-JYBKSBB5.js";import{a as q}from"./chunk-4NO7MHS7.js";import{a as Ke,b as be,c as xe}from"./chunk-RGOBWOBB.js";import{a as Se,b as Re}from"./chunk-PEUTCG3B.js";import"./chunk-PEJALHXK.js";import"./chunk-SC5M74NM.js";import{A as Xe,B as Qe,C as Ye,D as Ze,M as er,a as De,b as Be,c as Ce,d as Ee,f as _e,g as je,h as ve,i as Ae,k as Te,l as Ie,m as Oe,n as Ue,o as Ve,p as $e,q as Me,r as Ne,s as ze,t as Je,u as He,v as qe,w as Le,x as Fe,y as We,z as Ge}from"./chunk-UBBZWWRB.js";import"./chunk-SHDHMKMJ.js";import{a as te,c as ye,h as me}from"./chunk-BKVPSPG4.js";import{a as L}from"./chunk-NJ3AZYQD.js";import{a as Pe}from"./chunk-IEOSSSB5.js";import"./chunk-7TKJHKC2.js";import{b as ge,c as fe}from"./chunk-7HRKWTBB.js";import{a as Z,b as ee,c as re,d as oe,e as se,f as ie,g as ae,h as ce,i as le,j as ue,k as de,l as pe}from"./chunk-4UT2CLAT.js";import{a as ne}from"./chunk-FUUTGGJS.js";import{c as U,d as V,e as $,f as M,g as N,h as z,i as J,j as H}from"./chunk-2ACBWC7K.js";var j="kanonak-credentials",u="credentials",nr=1,f=class{async get(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readonly"),i=s.objectStore(u).get(e);i.onsuccess=()=>o(i.result??null),i.onerror=()=>a(new Error(`IndexedDB read failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async store(r,e){let t=d(r),o=await h();return new Promise((a,s)=>{let l=o.transaction(u,"readwrite"),c=l.objectStore(u).put(e,t);c.onsuccess=()=>a(),c.onerror=()=>s(new Error(`IndexedDB write failed for '${t}': ${c.error?.message}`)),l.oncomplete=()=>o.close()})}async remove(r){let e=d(r),t=await h();return new Promise((o,a)=>{let s=t.transaction(u,"readwrite"),i=s.objectStore(u).delete(e);i.onsuccess=()=>o(),i.onerror=()=>a(new Error(`IndexedDB delete failed for '${e}': ${i.error?.message}`)),s.oncomplete=()=>t.close()})}async list(){let r=await h();return new Promise((e,t)=>{let o=r.transaction(u,"readonly"),s=o.objectStore(u).getAllKeys();s.onsuccess=()=>e(s.result??[]),s.onerror=()=>t(new Error(`IndexedDB list failed: ${s.error?.message}`)),o.oncomplete=()=>r.close()})}};function h(){return new Promise((n,r)=>{let e=indexedDB.open(j,nr);e.onupgradeneeded=()=>{let t=e.result;t.objectStoreNames.contains(u)||t.createObjectStore(u)},e.onsuccess=()=>n(e.result),e.onerror=()=>r(new Error(`Failed to open IndexedDB '${j}': ${e.error?.message}
2
2
  Credential storage requires IndexedDB support in your browser.`))})}async function A(){let n=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),r=await crypto.subtle.exportKey("jwk",n.publicKey);return{signingKey:n.privateKey,publicKeyJwk:r}}async function K(){let n=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign"]),r=await crypto.subtle.exportKey("jwk",n.publicKey),e=await crypto.subtle.exportKey("jwk",n.privateKey);return{keys:{signingKey:n.privateKey,publicKeyJwk:r},dpopKeyPair:{publicKey:r,privateKey:e}}}async function b(n){return{signingKey:await crypto.subtle.importKey("jwk",n.privateKey,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),publicKeyJwk:n.publicKey}}async function x(n,r,e,t,o){let a={alg:"ES256",typ:"dpop+jwt",jwk:{kty:n.publicKeyJwk.kty,crv:n.publicKeyJwk.crv,x:n.publicKeyJwk.x,y:n.publicKeyJwk.y}},s={jti:crypto.randomUUID(),htm:r.toUpperCase(),htu:e,iat:Math.floor(Date.now()/1e3)};return t&&(s.ath=await sr(t)),o&&(s.nonce=o),await or(a,s,n.signingKey)}function S(n){return!n||n.length===0?!1:n.some(r=>r.toUpperCase()==="ES256")}async function or(n,r,e){let t=v(JSON.stringify(n)),o=v(JSON.stringify(r)),a=new TextEncoder().encode(`${t}.${o}`),s=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},e,a),l=B(s);return`${t}.${o}.${l}`}async function sr(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return B(e)}function v(n){let r=new TextEncoder().encode(n);return B(r.buffer)}function B(n){let r=new Uint8Array(n),e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var ir=300*1e3,R=class{credentialBackend;callbackUrl;constructor(r){this.credentialBackend=new f,this.callbackUrl=r??`${window.location.origin}/browser/callback.html`}async authorize(r){let e=d(r),t=await this.discover(e);if(!t)return{success:!1,error:`No OAuth discovery endpoint found for '${e}'.`};if(!t.authorizationEndpoint||!t.tokenEndpoint)return{success:!1,error:`OAuth metadata incomplete for '${e}'.`};let o=S(t.dpopSigningAlgValuesSupported),a=null,s=null;if(o){let g=await K();a=g.keys,s=g.dpopKeyPair}let l=await this.credentialBackend.get(e),i=l?.clientId??null,c=l?.clientSecret??null;if(!i&&t.registrationEndpoint){let g=await this.registerClient(t.registrationEndpoint);if(!g)return{success:!1,error:`Dynamic client registration failed for '${e}'.`};i=g.clientId,c=g.clientSecret??null}if(!i)return{success:!1,error:`No OAuth client credentials for '${e}'.`};let m=ar(),p=await cr(m),D=lr(),I=ur(t.authorizationEndpoint,i,this.callbackUrl,D,p),y=await this.openAuthPopup(I,D);if(!y)return{success:!1,error:"Authorization timed out or was cancelled."};if(y.error)return{success:!1,error:`Authorization failed: ${y.error}`};if(!y.code)return{success:!1,error:"No authorization code received."};if(y.state!==D)return{success:!1,error:"State mismatch \u2014 possible CSRF attack."};let P=await this.exchangeCode(t.tokenEndpoint,i,c,y.code,this.callbackUrl,m,a);if(!P)return{success:!1,error:"Token exchange failed."};let O={clientId:i,clientSecret:c,accessToken:P.accessToken??null,refreshToken:P.refreshToken??null,expiresAt:P.expiresIn?new Date(Date.now()+P.expiresIn*1e3).toISOString():null,tokenEndpoint:t.tokenEndpoint,dpopKeyPair:s};return await this.credentialBackend.store(e,O),{success:!0,host:e}}async getCredentialWithKeys(r){let e=await this.credentialBackend.get(r);if(!e)return null;let t=null;return e.dpopKeyPair&&(t=await b(e.dpopKeyPair)),{credential:e,dpopKeys:t}}async logout(r){let e=d(r);return await this.credentialBackend.remove(e),{success:!0,host:e}}async listAuthenticated(){return this.credentialBackend.list()}async discover(r){for(let e of[`https://${r}/.well-known/oauth-authorization-server`,`https://${r}/.well-known/openid-configuration`])try{let t=await w(e);if(!t.ok)continue;let o=await t.json();return{issuer:k(o.issuer),authorizationEndpoint:k(o.authorization_endpoint),tokenEndpoint:k(o.token_endpoint),registrationEndpoint:k(o.registration_endpoint),revocationEndpoint:k(o.revocation_endpoint),dpopSigningAlgValuesSupported:T(o.dpop_signing_alg_values_supported),codeChallengeMethodsSupported:T(o.code_challenge_methods_supported)}}catch{continue}return null}async registerClient(r){try{let e=await w(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak Browser",redirect_uris:[this.callbackUrl],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})});if(!e.ok)return null;let t=await e.json(),o=t.client_id;return o?{clientId:o,clientSecret:t.client_secret}:null}catch{return null}}openAuthPopup(r,e){return new Promise(t=>{let o=window.open(r,"kanonak-auth","width=500,height=700,menubar=no,toolbar=no,location=yes,status=no");if(!o){t(null);return}let a=setTimeout(()=>{i(),t(null)},ir),s=c=>{c.origin===window.location.origin&&(!c.data||c.data.type!=="kanonak-auth-callback"||(i(),t({code:c.data.code??void 0,state:c.data.state??void 0,error:c.data.error??void 0})))},l=setInterval(()=>{o.closed&&(i(),t(null))},500),i=()=>{clearTimeout(a),clearInterval(l),window.removeEventListener("message",s);try{o.close()}catch{}};window.addEventListener("message",s)})}async exchangeCode(r,e,t,o,a,s,l){let i=new URLSearchParams({grant_type:"authorization_code",client_id:e,code:o,redirect_uri:a,code_verifier:s});t&&i.set("client_secret",t);let c={"Content-Type":"application/x-www-form-urlencoded"};l&&(c.DPoP=await x(l,"POST",r));try{let m=await w(r,{method:"POST",headers:c,body:i.toString()});if(!m.ok)return null;let p=await m.json();return{accessToken:p.access_token,refreshToken:p.refresh_token,expiresIn:typeof p.expires_in=="number"?p.expires_in:void 0}}catch{return null}}};function ar(){let n=new Uint8Array(32);return crypto.getRandomValues(n),C(n.buffer)}async function cr(n){let r=new TextEncoder().encode(n),e=await crypto.subtle.digest("SHA-256",r);return C(e)}function lr(){let n=new Uint8Array(16);return crypto.getRandomValues(n),C(n.buffer)}function ur(n,r,e,t,o){let a=new URLSearchParams({client_id:r,response_type:"code",redirect_uri:e,state:t,code_challenge:o,code_challenge_method:"S256"});return`${n}?${a}`}function C(n){let r=new Uint8Array(n),e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function k(n){return typeof n=="string"?n:null}function T(n){return Array.isArray(n)?n.filter(r=>typeof r=="string"):null}export{Le as AmbiguousReferenceRule,le as BooleanStatement,f as BrowserCredentialBackend,R as BrowserOAuthFlow,Ye as ClassDefinitionRule,Ue as ClassHierarchyCycleRule,ee as DefinedKanonak,He as DefinitionPropertyReferenceRule,ke as EdgeType,te as EmbeddedKanonak,Te as EmbeddedKanonakTypeRule,de as EmbeddedStatement,he as GraphBuilder,Y as HttpKanonakDocumentRepository,Ie as ImportExistenceRule,q as InMemoryKanonakDocumentRepository,F as KANONAK_USER_AGENT,Z as Kanonak,be as KanonakDocumentPositions,me as KanonakObjectParser,er as KanonakObjectValidator,L as KanonakParser,ne as KanonakUri,Se as KanonakUriBuilder,pe as ListStatement,Ze as MarkdownLinkRule,ye as MarkdownStatement,ze as NamespaceImportCycleRule,_e as NamespacePrefixRule,we as NodeType,ce as NumberStatement,We as ObjectPropertyImportRule,Ge as ObjectPropertyValueValidationRule,Ce as OntologyValidationError,De as OntologyValidationResult,Xe as PropertyDomainRule,Ve as PropertyHierarchyCycleRule,Ke as PropertyMetadata,Fe as PropertyRangeReferenceRule,$e as PropertyRangeRequiredRule,ve as PropertyTypeSpecificityRule,Qe as PropertyValueTypeRule,X as PublisherConfigResolver,Q as PublisherIndex,oe as ReferenceKanonak,ue as ReferenceStatement,je as ResourceNamingRule,ge as ResourceResolver,Pe as ResourceTypeClassifier,ie as ScalarStatement,se as Statement,ae as StringStatement,Me as SubClassOfReferenceRule,Ne as SubPropertyOfReferenceRule,re as SubjectKanonak,Ae as SubjectKanonakTypeRequiredRule,fe as TypeResolver,Je as UnresolvedPredicateRule,Oe as UnresolvedReferenceRule,Ee as ValidationContext,Be as ValidationSeverity,qe as XsdImportRule,S as browserServerSupportsDPoP,tr as buildOntologyModel,U as compareVersions,x as createBrowserDPoPProof,M as createVersion,rr as findDerivation,Re as findInstancesByType,$ as formatVersion,K as generateBrowserDPoPKeyPair,A as generateBrowserDPoPKeys,G as getKanonakUserAgent,_ as hasValidToken,b as importDPoPKeys,z as isCompatibleVersion,E as isExpired,J as isMajorCompatible,w as kanonakFetch,d as normalizeHost,N as parseVersionString,xe as parseWithPositions,H as pickHighestDocument,W as setKanonakUserAgent,V as versionsEqual};
@@ -1,2 +1,2 @@
1
1
  import{J as W,K as X}from"./chunk-UBBZWWRB.js";import{b as B,c as V,h as w}from"./chunk-BKVPSPG4.js";import{a as b,d as K,e as q,f as z}from"./chunk-IEOSSSB5.js";import{a as D,f as E,h as F,j as N,k as Y,m as v}from"./chunk-7TKJHKC2.js";import{c as G,d as x}from"./chunk-4UT2CLAT.js";import{a as L}from"./chunk-FUUTGGJS.js";import{d as U}from"./chunk-2ACBWC7K.js";var Q=(t=>(t.Class="Class",t.DatatypeProperty="DatatypeProperty",t.ObjectProperty="ObjectProperty",t.AnnotationProperty="AnnotationProperty",t.Instance="Instance",t.Datatype="Datatype",t.Unknown="Unknown",t))(Q||{}),Z=(p=>(p.InstanceOf="instanceOf",p.SubClassOf="subClassOf",p.Domain="domain",p.Range="range",p.ObjectRelationship="objectRelationship",p.SubPropertyOf="subPropertyOf",p.PropertyValue="propertyValue",p.EmbeddedLink="embeddedLink",p))(Z||{}),I=class{static async buildFromRepository(e){let a=await new w().parseKanonaks(e),o=await e.getAllDocumentsAsync(),s=[],i=[],t=new Set,p=new Set,g=new Map;for(let u of a){let l=u;l.name&&(b.isClassType(l)&&t.add(l.name),(b.isObjectPropertyType(l)||b.isGenericPropertyType(l))&&p.add(l.name))}for(let u of o)for(let[l,f]of Object.entries(u.body))p.has(l)&&f?.range&&typeof f.range=="string"&&g.set(l,f.range);let y=new Map;for(let u of a){let l=u;l.name&&y.set(l.name,l)}for(let u of o){let l=u.metadata.namespace_,f=l?`${l.publisher}/${l.package_}`:"",c=l?.version?`${l.version.major}.${l.version.minor}.${l.version.patch}`:"",d=H(u);for(let[k,m]of Object.entries(u.body)){if(!m||typeof m!="object")continue;let P=y.get(k),h="Unknown";if(P){let T=P;b.isClassType(T)?h="Class":b.isObjectPropertyType(T)?h="ObjectProperty":b.isDatatypePropertyType(T)?h="DatatypeProperty":b.isAnnotationPropertyType(T)?h="AnnotationProperty":b.isDatatypeType(T)?h="Datatype":b.isGenericPropertyType(T)?h="ObjectProperty":b.isInstanceOfKnownClass(T,t)&&(h="Instance")}let j=f&&c?`${f}/${k}@${c}`:k,A={};for(let[T,$]of Object.entries(m))T!=="type"&&(typeof $!="object"||$===null)&&(A[T]=$);s.push({id:j,label:m.label??k,type:h,namespace:f,properties:A}),J(j,m,h,t,p,i,f,c,d),_(j,m,p,g,s,i,f,c,d),ue(j,P,i)}}return{nodes:s,edges:i}}static buildFromDocument(e){let r=[],a=[],o=e.metadata.namespace_,s=o?.version?`${o.version.major}.${o.version.minor}.${o.version.patch}`:"",i=o?`${o.publisher}/${o.package_}`:"",t=new Set,p=new Set,g=new Map,y=H(e);for(let[f,c]of Object.entries(e.body)){let d=c?.type;d&&(pe(d,y)&&t.add(f),ce(d,y)&&(p.add(f),c.range&&typeof c.range=="string"&&g.set(f,c.range)))}for(let[f,c]of Object.entries(e.body)){if(!c||typeof c!="object")continue;let d=c.type,k=le(d,f,t,y),m=i&&s?`${i}/${f}@${s}`:f,P={};for(let[h,j]of Object.entries(c))h!=="type"&&(typeof j!="object"||j===null)&&(P[h]=j);r.push({id:m,label:c.label??f,type:k,namespace:i,properties:P}),J(m,c,k,t,p,a,i,s,y),_(m,c,p,g,r,a,i,s,y)}let u=new Set(r.map(f=>f.id)),l=a.filter(f=>u.has(f.source)&&u.has(f.target));return{nodes:r,edges:l}}};function H(n,e){let r=new Map;if(n.metadata?.imports)for(let[a,o]of Object.entries(n.metadata.imports))for(let s of o){let i=s.alias??s.packageName,t=s.version,p=`${t.major}.${t.minor}.${t.patch}`;r.set(i,{publisher:a,package_:s.packageName,version:p})}return r}var ee={"kanonak.org/core-rdf/Class":"Class","kanonak.org/core-owl/Class":"Class","kanonak.org/core-rdfs/Class":"Class","kanonak.org/core-owl/ObjectProperty":"ObjectProperty","kanonak.org/core-owl/DatatypeProperty":"DatatypeProperty","kanonak.org/core-owl/AnnotationProperty":"AnnotationProperty","kanonak.org/core-rdf/Property":"ObjectProperty","kanonak.org/core-rdfs/Datatype":"Datatype"},ie=new Set(["kanonak.org/core-owl/ObjectProperty","kanonak.org/core-owl/DatatypeProperty","kanonak.org/core-owl/AnnotationProperty","kanonak.org/core-rdf/Property"]);function M(n,e){if(n.includes(".")){let r=n.indexOf("."),a=n.substring(0,r),o=n.substring(r+1),s=e.get(a);if(s)return`${s.publisher}/${s.package_}/${o}`}return null}function pe(n,e){let r=M(n,e);return r?ee[r]==="Class":!1}function ce(n,e){let r=M(n,e);return r?ie.has(r):!1}function le(n,e,r,a){if(!n||n==="Package")return"Unknown";let o=M(n,a);if(o){let i=ee[o];if(i)return i;let t=o.split("/").pop()?.split("@")[0]??"";return r.has(t)?"Instance":"Unknown"}let s=n.split(".").pop()??n;return r.has(s)?"Instance":"Unknown"}var ne=new Set(["type","label","comment","version","publisher","imports","license","match","alias","package"]);function J(n,e,r,a,o,s,i,t,p){let g=e.type,y=e.subClassOf;if(y){let c=Array.isArray(y)?y:[y];for(let d of c)typeof d=="string"&&s.push({source:n,target:O(d,i,t,p),type:"subClassOf",label:"subClassOf"})}let u=e.subPropertyOf;if(u){let c=Array.isArray(u)?u:[u];for(let d of c)typeof d=="string"&&s.push({source:n,target:O(d,i,t,p),type:"subPropertyOf",label:"subPropertyOf"})}if(r==="Instance"&&g){let c=g.split(".").pop()??g;s.push({source:n,target:O(c,i,t,p),type:"instanceOf",label:"type"})}if(r==="Instance")for(let[c,d]of Object.entries(e)){if(ne.has(c)||!o.has(c))continue;let k=Array.isArray(d)?d:[d];for(let m of k)typeof m=="string"&&fe(m)&&s.push({source:n,target:O(m,i,t,p),type:"propertyValue",label:c,propertyId:O(c,i,t,p)})}let l=r==="ObjectProperty"||r==="DatatypeProperty",f=e.domain&&e.range;if((l||f)&&e.domain&&e.range){let c=typeof e.domain=="string"?e.domain:null,d=typeof e.range=="string"?e.range:null;c&&d&&s.push({source:O(c,i,t,p),target:O(d,i,t,p),type:"objectRelationship",label:e.label??n.split("/").pop()??"",propertyId:n})}}function _(n,e,r,a,o,s,i,t,p){for(let[g,y]of Object.entries(e)){if(ne.has(g)||typeof y!="object"||y===null||Array.isArray(y))continue;let u=y,l=`${n}/${g}`,f=a.get(g),c=f?f.split(".").pop()??f:"Unknown",d={};for(let[m,P]of Object.entries(u))(typeof P!="object"||P===null)&&(d[m]=P);o.push({id:l,label:`${c} (embedded)`,type:"Instance",namespace:i,properties:d});let k=i&&t?`${i}/${g}@${t}`:g;s.push({source:n,target:l,type:"propertyValue",label:g,propertyId:r.has(g)?k:void 0}),f&&s.push({source:l,target:O(c,i,t,p),type:"instanceOf",label:"type (inferred)"}),_(l,u,r,a,o,s,i,t,p)}}function ue(n,e,r){let a=e?.statement;if(Array.isArray(a))for(let o of a){if(!(o instanceof V))continue;let s=o.predicate?.subject?.name??"";for(let i of o.links){let t=i.target?.subject;if(!t)continue;let p=t.version,g=p&&typeof p.major=="number"?`@${p.major}.${p.minor}.${p.patch}`:"";r.push({source:n,target:`${t.publisher}/${t.package_}/${t.name}${g}`,type:"embeddedLink",label:s})}}}function fe(n){return!(!n||n.includes(" ")||n.includes(`
2
- `)||n.startsWith("http://")||n.startsWith("https://")||/^\d{4}-\d{2}/.test(n)||/^\d+(\.\d+)?$/.test(n))}function O(n,e,r,a){if(n.includes("@")&&n.includes("/"))return n;if(n.includes(".")){let o=n.indexOf("."),s=n.substring(0,o),i=n.substring(o+1);if(a){let t=a.get(s);if(t)return`${t.publisher}/${t.package_}/${i}@${t.version}`}return e&&r?`${e}/${i}@${r}`:i}return e&&r?`${e}/${n}@${r}`:n}function de(n){if(!n.expiresAt)return!1;let e=new Date(n.expiresAt),r=300*1e3;return e.getTime()<=Date.now()+r}function Re(n){return!!n.accessToken&&!de(n)}function Se(n){let e=n.replace(/^https?:\/\//,"").replace(/^git:\/\//,"").replace(/\/+$/,"").trim();if(!e)throw new Error("Publisher host cannot be empty");return e}var C="kanonak.org",S="core-rdf",re="core-xsd",te={publisher:C,package_:S,name:"subClassOf"},oe={publisher:C,package_:S,name:"label"},ye={publisher:C,package_:S,name:"comment"},se={publisher:C,package_:"core-owl",name:"oneOf"},ae=n=>n;function ge(n){let e=Y(n,te);if(e)return[e];let r=[];for(let a of v(n,te))a instanceof x&&r.push(a.subject);return r}function me(n,e,r){if(e.publisher===C&&e.package_===S&&e.name==="Literal")return{kind:"datatype",uri:e};let o=E(n,e);if(o){let s=ae(o);if(b.isDatatypeType(s))return{kind:"datatype",uri:e};if(b.isClassType(s))return{kind:"class",uri:K(o)??e,localName:o.name}}return e.publisher===C&&e.package_===re?{kind:"datatype",uri:e}:r==="datatype"?{kind:"datatype",uri:e}:{kind:"class",uri:e,localName:e.name}}function be(n,e,r){if(!e.range)throw new Error(`Property ${e.uri.publisher}/${e.uri.package_}/${e.uri.name} has no rdfs.range; every property must declare a range. Validate the ontology before introspecting it.`);let a=me(n,e.range,e.kind),o=e.kind==="object"?"object":e.kind==="datatype"?"datatype":a.kind==="class"?"object":"datatype";return{uri:e.uri,localName:e.uri.name,kind:o,range:a,...e.label!==void 0?{label:e.label}:{},...e.comment!==void 0?{comment:e.comment}:{},...r??{}}}var R=n=>new L(C,re,n);function ke(n){return typeof n=="boolean"?R("boolean"):typeof n=="number"?Number.isInteger(n)?R("integer"):R("decimal"):R("string")}function he(n,e){let r=[];for(let a of v(e,se))if(a instanceof x){let o=E(n,a.subject),s=(o?K(o):void 0)??a.subject,i=o?N(o,oe):void 0;r.push({kind:"individual",uri:s,localName:s.name,...i!==void 0?{label:i}:{}})}else a instanceof B&&r.push({kind:"literal",value:a.value,datatype:ke(a.value)});return r}function Pe(n,e,r,a){let o=q(n,e),s=D(e);return z(n,e).filter(t=>r?!0:t.domains.some(p=>D(p)===s)).map(t=>be(n,t,X(a,o,t.uri)))}async function Te(n,e,r){let a=n.metadata?.namespace_;if(!a)throw new Error("buildOntologyModel: document has no namespace (publisher/package/version).");let o=r?.includeInherited??!1,s=await new w().parseKanonaks(e),i=W(s),t=[],p=[],g=new Set;for(let y of s){if(!(y instanceof G)||!b.isClassType(ae(y)))continue;let u=K(y);if(!u||u.publisher!==a.publisher||u.package_!==a.package_||u.version&&a.version&&!U(u.version,a.version))continue;let l=D(u);if(g.has(l))continue;g.add(l);let f=ge(y).map(k=>({uri:k,localName:k.name})),c=N(y,oe),d=N(y,ye);t.push({uri:u,localName:u.name,superClasses:f,properties:Pe(s,u,o,i),...c!==void 0?{label:c}:{},...d!==void 0?{comment:d}:{}}),F(y,se)&&p.push({uri:u,localName:u.name,members:he(s,y),...c!==void 0?{label:c}:{},...d!==void 0?{comment:d}:{}})}return{classes:t,enums:p}}export{Q as a,Z as b,I as c,de as d,Re as e,Se as f,Te as g};
2
+ `)||n.startsWith("http://")||n.startsWith("https://")||/^\d{4}-\d{2}/.test(n)||/^\d+(\.\d+)?$/.test(n))}function O(n,e,r,a){if(n.includes("@")&&n.includes("/"))return n;if(n.includes(".")){let o=n.indexOf("."),s=n.substring(0,o),i=n.substring(o+1);if(a){let t=a.get(s);if(t)return`${t.publisher}/${t.package_}/${i}@${t.version}`}return e&&r?`${e}/${i}@${r}`:i}return e&&r?`${e}/${n}@${r}`:n}function de(n){if(!n.expiresAt)return!1;let e=new Date(n.expiresAt),r=300*1e3;return e.getTime()<=Date.now()+r}function Se(n){return!!n.accessToken&&!de(n)}function Re(n){let e=n.replace(/^https?:\/\//,"").replace(/^git:\/\//,"").replace(/\/+$/,"").trim();if(!e)throw new Error("Publisher host cannot be empty");return e}var C="kanonak.org",R="core-rdf",re="core-xsd",te={publisher:C,package_:R,name:"subClassOf"},oe={publisher:C,package_:R,name:"label"},ye={publisher:C,package_:R,name:"comment"},se={publisher:C,package_:"core-owl",name:"oneOf"},ae=n=>n;function ge(n){let e=Y(n,te);if(e)return[e];let r=[];for(let a of v(n,te))a instanceof x&&r.push(a.subject);return r}function me(n,e,r){if(e.publisher===C&&e.package_===R&&e.name==="Literal")return{kind:"datatype",uri:e};let o=E(n,e);if(o){let s=ae(o);if(b.isDatatypeType(s))return{kind:"datatype",uri:e};if(b.isClassType(s))return{kind:"class",uri:K(o)??e,localName:o.name}}return e.publisher===C&&e.package_===re?{kind:"datatype",uri:e}:r==="datatype"?{kind:"datatype",uri:e}:{kind:"class",uri:e,localName:e.name}}function be(n,e,r){if(!e.range)throw new Error(`Property ${e.uri.publisher}/${e.uri.package_}/${e.uri.name} has no rdfs.range; every property must declare a range. Validate the ontology before introspecting it.`);let a=me(n,e.range,e.kind),o=e.kind==="object"?"object":e.kind==="datatype"?"datatype":a.kind==="class"?"object":"datatype";return{uri:e.uri,localName:e.uri.name,kind:o,range:a,...e.label!==void 0?{label:e.label}:{},...e.comment!==void 0?{comment:e.comment}:{},...r??{}}}var S=n=>new L(C,re,n);function ke(n){return typeof n=="boolean"?S("boolean"):typeof n=="number"?Number.isInteger(n)?S("integer"):S("decimal"):S("string")}function he(n,e){let r=[];for(let a of v(e,se))if(a instanceof x){let o=E(n,a.subject),s=(o?K(o):void 0)??a.subject,i=o?N(o,oe):void 0;r.push({kind:"individual",uri:s,localName:s.name,...i!==void 0?{label:i}:{}})}else a instanceof B&&r.push({kind:"literal",value:a.value,datatype:ke(a.value)});return r}function Pe(n,e,r,a){let o=q(n,e),s=D(e);return z(n,e).filter(t=>r?!0:t.domains.some(p=>D(p)===s)).map(t=>be(n,t,X(a,o,t.uri)))}async function Te(n,e,r){let a=n.metadata?.namespace_;if(!a)throw new Error("buildOntologyModel: document has no namespace (publisher/package/version).");let o=r?.includeInherited??!1,s=await new w().parseKanonaks(e),i=W(s),t=[],p=[],g=new Set;for(let y of s){if(!(y instanceof G)||!b.isClassType(ae(y)))continue;let u=K(y);if(!u||u.publisher!==a.publisher||u.package_!==a.package_||u.version&&a.version&&!U(u.version,a.version))continue;let l=D(u);if(g.has(l))continue;g.add(l);let f=ge(y).map(k=>({uri:k,localName:k.name})),c=N(y,oe),d=N(y,ye);t.push({uri:u,localName:u.name,superClasses:f,properties:Pe(s,u,o,i),...c!==void 0?{label:c}:{},...d!==void 0?{comment:d}:{}}),F(y,se)&&p.push({uri:u,localName:u.name,members:he(s,y),...c!==void 0?{label:c}:{},...d!==void 0?{comment:d}:{}})}return{classes:t,enums:p}}export{Q as a,Z as b,I as c,de as d,Se as e,Re as f,Te as g};
package/dist/index.d.ts CHANGED
@@ -21,8 +21,8 @@ export type { IKanonakDocumentRepository } from '@kanonak-protocol/types/documen
21
21
  export type { IKanonakParser } from '@kanonak-protocol/types/document/parsing';
22
22
  export type { KanonakDocument, KanonakMetadata, Namespace, Import, Version, DocumentReference, ParseResult, ParseError } from '@kanonak-protocol/types/document/models/types';
23
23
  export { VersionOperator } from '@kanonak-protocol/types/document/models/enums';
24
- export { CredentialStore, createAuthenticatedFetch, generateDPoPKeyPair, createDPoPProof, serverSupportsDPoP, isExpired, hasValidToken, normalizeHost, } from './auth/index.js';
25
- export type { CredentialBackend, StoredCredential, DPoPKeyPair, AuthenticatedFetchFn, } from './auth/index.js';
24
+ export { CredentialStore, DeviceCertificateStore, createAuthenticatedFetch, generateDPoPKeyPair, createDPoPProof, serverSupportsDPoP, isExpired, hasValidToken, normalizeHost, } from './auth/index.js';
25
+ export type { SecretBackend, CredentialBackend, StoredCredential, DeviceEnrollmentRecord, DPoPKeyPair, AuthenticatedFetchFn, } from './auth/index.js';
26
26
  export { kanonakFetch, setKanonakUserAgent, getKanonakUserAgent, KANONAK_USER_AGENT, } from './http/kanonakFetch.js';
27
27
  export { loadLockFile, saveLockFile, computeIntegrity, } from './lock/index.js';
28
28
  export type { LockFile, LockEntry } from './lock/index.js';
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import{a as kr,b as hr,c as br,d as Pr,e as he}from"./chunk-CR55WXIN.js";import{a as mn,c as Ce,e as Le,h as Fe,i as Me,j as fn}from"./chunk-V72IVYR4.js";import{a as fr,b as yr,c as gr,d as L,e as F,f as l,g as yn}from"./chunk-U7LVFPEO.js";import{a as dn}from"./chunk-VWS25JH4.js";import"./chunk-QHABFCRC.js";import{a as Ut,b as _t,c as Lt,d as Ft,e as Mt,f as Zt,g as Xt,h as Qt,i as er}from"./chunk-GMEPM2QQ.js";import{a as Ht,b as zt,c as Wt,d as b,f as Gt,g as Jt,h as Yt}from"./chunk-JYBKSBB5.js";import{a as Bt}from"./chunk-4NO7MHS7.js";import{a as Cr,b as Sr,c as Rr,d as Er}from"./chunk-RGOBWOBB.js";import{a as xr,b as Vr}from"./chunk-PEUTCG3B.js";import{a as vr}from"./chunk-PEJALHXK.js";import{a as qt}from"./chunk-SC5M74NM.js";import{A as sn,B as cn,C as ln,D as un,M as pn,a as Or,b as Dr,c as Tr,d as Nr,e as Br,f as Ur,g as _r,h as Lr,i as Fr,j as Mr,k as Hr,l as zr,m as Wr,n as Gr,o as Jr,p as qr,q as Yr,r as Zr,s as Xr,t as Qr,u as en,v as tn,w as rn,x as nn,y as on,z as an}from"./chunk-UBBZWWRB.js";import"./chunk-SHDHMKMJ.js";import{a as y,b as ue,c as or,d as U,e as Ue,f as pr,g as dr,h as E}from"./chunk-BKVPSPG4.js";import{a as S}from"./chunk-NJ3AZYQD.js";import{a as mr,b as be,c as Ir,d as g,e as Kr,f as $r,g as jr,h as Ar}from"./chunk-IEOSSSB5.js";import{f as _,k as x,l as Pe,m as we,n as _e}from"./chunk-7TKJHKC2.js";import{b as ar,c as ir,d as R,e as sr,f as cr,h as lr,k as ur}from"./chunk-7HRKWTBB.js";import{a as tr,b as le,c as f,d as h,e as nr,f as pe,g as de,h as me,i as fe,j as ye,k as ge,l as ke}from"./chunk-4UT2CLAT.js";import{a as rr}from"./chunk-FUUTGGJS.js";import{a as jt,b as ce,c as B,d as At,e as k,f as Vt,g as Ot,h as Dt,i as Tt,j as Nt}from"./chunk-2ACBWC7K.js";import{a as wr}from"./chunk-ODIECDN7.js";import{VersionOperator as Si}from"@kanonak-protocol/types/document/models/enums";import{existsSync as Vn,readFileSync as On}from"fs";import{homedir as Dn}from"os";import{join as Tn}from"path";import{execFile as gn}from"child_process";import{promisify as kn}from"util";var M=kn(gn),H="kanonak",z="/usr/bin/security",I=class{async get(e){let t=l(e);try{let{stdout:n}=await M(z,["find-generic-password","-s",H,"-a",t,"-w"],{timeout:1e4});try{return JSON.parse(n.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(n){if(He(n,44))return null;throw new Error(`macOS Keychain read failed for '${t}': ${W(n)}
1
+ import{a as yr,b as gr,c as kr,d as hr,e as ge}from"./chunk-CR55WXIN.js";import{a as pn,c as Pe,e as _e,h as Ue,i as Fe,j as dn}from"./chunk-V72IVYR4.js";import{a as dr,b as mr,c as fr,d as L,e as M,f as l,g as mn}from"./chunk-NUXUITUC.js";import{a as un}from"./chunk-VWS25JH4.js";import"./chunk-QHABFCRC.js";import{a as Ot,b as Nt,c as _t,d as Ut,e as Ft,f as qt,g as Yt,h as Zt,i as Xt}from"./chunk-GMEPM2QQ.js";import{a as Lt,b as Mt,c as Ht,d as R,f as zt,g as Wt,h as Jt}from"./chunk-JYBKSBB5.js";import{a as Bt}from"./chunk-4NO7MHS7.js";import{a as Pr,b as wr,c as Sr,d as Rr}from"./chunk-RGOBWOBB.js";import{a as Er,b as jr}from"./chunk-PEUTCG3B.js";import{a as Cr}from"./chunk-PEJALHXK.js";import{a as Gt}from"./chunk-SC5M74NM.js";import{A as on,B as an,C as sn,D as cn,M as ln,a as Tr,b as Ar,c as Dr,d as Vr,e as Br,f as Or,g as Nr,h as _r,i as Ur,j as Fr,k as Lr,l as Mr,m as Hr,n as zr,o as Wr,p as Gr,q as Jr,r as qr,s as Yr,t as Zr,u as Xr,v as Qr,w as en,x as tn,y as rn,z as nn}from"./chunk-UBBZWWRB.js";import"./chunk-SHDHMKMJ.js";import{a as y,b as ce,c as rr,d as U,e as Oe,f as lr,g as ur,h as K}from"./chunk-BKVPSPG4.js";import{a as x}from"./chunk-NJ3AZYQD.js";import{a as pr,b as ke,c as vr,d as g,e as xr,f as Ir,g as Kr,h as $r}from"./chunk-IEOSSSB5.js";import{f as F,k as $,l as he,m as be,n as Ne}from"./chunk-7TKJHKC2.js";import{b as nr,c as or,d as I,e as ir,f as ar,h as sr,k as cr}from"./chunk-7HRKWTBB.js";import{a as Qt,b as se,c as f,d as h,e as tr,f as le,g as ue,h as pe,i as de,j as me,k as fe,l as ye}from"./chunk-4UT2CLAT.js";import{a as er}from"./chunk-FUUTGGJS.js";import{a as Kt,b as ae,c as _,d as $t,e as k,f as jt,g as Tt,h as At,i as Dt,j as Vt}from"./chunk-2ACBWC7K.js";import{a as br}from"./chunk-ODIECDN7.js";import{VersionOperator as Oa}from"@kanonak-protocol/types/document/models/enums";import{existsSync as Vn,readFileSync as Bn}from"fs";import{homedir as On}from"os";import{join as Nn}from"path";import{execFile as fn}from"child_process";import{promisify as yn}from"util";var H=yn(fn),gn="kanonak",z="/usr/bin/security",b=class{constructor(e=gn){this.service=e}service;async get(e){let t=l(e);try{let{stdout:n}=await H(z,["find-generic-password","-s",this.service,"-a",t,"-w"],{timeout:1e4});try{return JSON.parse(n.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(n){if(Le(n,44))return null;throw new Error(`macOS Keychain read failed for '${t}': ${W(n)}
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 n=l(e),o=JSON.stringify(t);try{await M(z,["add-generic-password","-s",H,"-a",n,"-U","-w",o],{timeout:1e4})}catch(a){throw new Error(`macOS Keychain write failed for '${n}': ${W(a)}
4
+ Try unlocking it via Keychain Access.app or running 'security unlock-keychain'.`)}}async store(e,t){let n=l(e),o=JSON.stringify(t);try{await H(z,["add-generic-password","-s",this.service,"-a",n,"-U","-w",o],{timeout:1e4})}catch(i){throw new Error(`macOS Keychain write failed for '${n}': ${W(i)}
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=l(e);try{await M(z,["delete-generic-password","-s",H,"-a",t],{timeout:1e4})}catch(n){if(He(n,44))return;console.warn(` Warning: macOS Keychain delete failed for '${t}': ${W(n)}
7
- The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await M(z,["dump-keychain"],{timeout:1e4}),t=[],n=!1;for(let o of e.split(`
8
- `))if(o.includes(`"svce"<blob>="${H}"`)&&(n=!0),n&&o.includes('"acct"<blob>=')){let a=o.match(/"acct"<blob>="([^"]+)"/);a&&t.push(a[1]),n=!1}return t}catch(e){return console.warn(` Warning: Could not enumerate Keychain entries: ${W(e)}`),[]}}};function He(r,e){return typeof r=="object"&&r!==null&&"code"in r&&r.code===e}function W(r){return r instanceof Error?r.message:String(r)}import{execFile as hn}from"child_process";import{promisify as bn}from"util";var Pn=bn(hn),G="kanonak:",v=class{async get(e){let t=G+l(e),n=`
9
- ${q}
6
+ On managed devices, your IT policy may block credential storage.`)}}async remove(e){let t=l(e);try{await H(z,["delete-generic-password","-s",this.service,"-a",t],{timeout:1e4})}catch(n){if(Le(n,44))return;console.warn(` Warning: macOS Keychain delete failed for '${t}': ${W(n)}
7
+ The credential may not have been fully removed.`)}}async list(){try{let{stdout:e}=await H(z,["dump-keychain"],{timeout:1e4}),t=[],n=!1;for(let o of e.split(`
8
+ `))if(o.includes(`"svce"<blob>="${this.service}"`)&&(n=!0),n&&o.includes('"acct"<blob>=')){let i=o.match(/"acct"<blob>="([^"]+)"/);i&&t.push(i[1]),n=!1}return t}catch(e){return console.warn(` Warning: Could not enumerate Keychain entries: ${W(e)}`),[]}}};function Le(r,e){return typeof r=="object"&&r!==null&&"code"in r&&r.code===e}function W(r){return r instanceof Error?r.message:String(r)}import{execFile as kn}from"child_process";import{promisify as hn}from"util";var bn=hn(kn),Pn="kanonak:",P=class{constructor(e=Pn){this.targetPrefix=e}targetPrefix;async get(e){let t=this.targetPrefix+l(e),n=`
9
+ ${J}
10
10
  $target = [Console]::In.ReadLine()
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:o}=await J(n,t),a=o.trim();return a?JSON.parse(a):null}catch{return null}}async store(e,t){let n=G+l(e),o=JSON.stringify(t),a=`
22
- ${q}
21
+ }`;try{let{stdout:o}=await G(n,t),i=o.trim();return i?JSON.parse(i):null}catch{return null}}async store(e,t){let n=this.targetPrefix+l(e),o=JSON.stringify(t),i=`
22
+ ${J}
23
23
  $target = [Console]::In.ReadLine()
24
24
  $json = [Console]::In.ReadLine()
25
25
  $bytes = [System.Text.Encoding]::Unicode.GetBytes($json)
@@ -35,12 +35,12 @@ try {
35
35
  if (-not $result) { throw "CredWrite failed" }
36
36
  } finally {
37
37
  [System.Runtime.InteropServices.Marshal]::FreeHGlobal($cred.CredentialBlob)
38
- }`;try{await J(a,`${n}
39
- ${o}`)}catch(i){throw new Error(`Windows Credential Manager write failed: ${String(i)}`)}}async remove(e){let t=G+l(e),n=`
40
- ${q}
38
+ }`;try{await G(i,`${n}
39
+ ${o}`)}catch(a){throw new Error(`Windows Credential Manager write failed: ${String(a)}`)}}async remove(e){let t=this.targetPrefix+l(e),n=`
40
+ ${J}
41
41
  $target = [Console]::In.ReadLine()
42
- [CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await J(n,t)}catch{}}async list(){let e=`
43
- ${q}
42
+ [CredMan]::CredDelete($target, 1, 0) | Out-Null`;try{await G(n,t)}catch{}}async list(){let e=`
43
+ ${J}
44
44
  ${wn}
45
45
  $prefix = [Console]::In.ReadLine()
46
46
  $count = 0
@@ -55,8 +55,8 @@ if ([CredMan]::CredEnumerate($null, 0, [ref]$count, [ref]$pCreds)) {
55
55
  }
56
56
  }
57
57
  [CredMan]::CredFree($pCreds)
58
- }`;try{let{stdout:t}=await J(e,G);return t.trim().split(`
59
- `).map(n=>n.trim()).filter(Boolean)}catch{return[]}}};async function J(r,e){for(let t of["pwsh","powershell"])try{return await Pn(t,["-NoProfile","-NonInteractive","-Command",r],{timeout:15e3,...e!==void 0&&{input:e}})}catch(n){if(t==="powershell")throw n}throw new Error("Neither pwsh nor powershell found")}var q=`
58
+ }`;try{let{stdout:t}=await G(e,this.targetPrefix);return t.trim().split(`
59
+ `).map(n=>n.trim()).filter(Boolean)}catch{return[]}}};async function G(r,e){for(let t of["pwsh","powershell"])try{return await bn(t,["-NoProfile","-NonInteractive","-Command",r],{timeout:15e3,...e!==void 0&&{input:e}})}catch(n){if(t==="powershell")throw n}throw new Error("Neither pwsh nor powershell found")}var J=`
60
60
  Add-Type -TypeDefinition @"
61
61
  using System;
62
62
  using System.Runtime.InteropServices;
@@ -87,13 +87,13 @@ public class CredMan {
87
87
  [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
88
88
  public static extern bool CredEnumerate(string filter, int flags, out int count, out IntPtr credentials);
89
89
  }
90
- "@`,wn="";import{execFile as Cn,spawn as Sn}from"child_process";import{promisify as Rn}from"util";var Z=Rn(Cn),Y="kanonak",K=class{async get(e){let t=l(e);try{let{stdout:n}=await Z("secret-tool",["lookup","service",Y,"publisher",t],{timeout:1e4}),o=n.trim();return o?JSON.parse(o):null}catch{return null}}async store(e,t){let n=l(e),o=JSON.stringify(t);await new Promise((a,i)=>{let s=Sn("secret-tool",["store","--label",`Kanonak: ${n}`,"service",Y,"publisher",n],{stdio:["pipe","ignore","ignore"],timeout:1e4});s.stdin.write(o),s.stdin.end(),s.on("close",c=>{c===0?a():i(new Error(`secret-tool store exited with code ${c}`))}),s.on("error",i)})}async remove(e){let t=l(e);try{await Z("secret-tool",["clear","service",Y,"publisher",t],{timeout:1e4})}catch{}}async list(){try{let{stdout:e}=await Z("secret-tool",["search","service",Y],{timeout:1e4}),t=[];for(let n of e.split(`
91
- `)){let o=n.match(/attribute\.publisher\s*=\s*(.+)/);o&&t.push(o[1].trim())}return t}catch{return[]}}};async function Se(){try{return await Z("sh",["-c","command -v secret-tool"],{timeout:5e3}),!0}catch{return!1}}import{existsSync as ze,mkdirSync as We,readFileSync as Ge,writeFileSync as Je}from"fs";import{createCipheriv as En,createDecipheriv as xn,randomBytes as qe}from"crypto";import{homedir as In}from"os";import{join as xe,dirname as Ye}from"path";var Xe=xe(In(),".config","kanonak"),$=xe(Xe,"keyring.key"),X=xe(Xe,"credentials.enc"),Ze="aes-256-gcm",Re=32,P=12,Ee=16,j=class{async get(e){let t=this.loadStore(),n=l(e);return t[n]??null}async store(e,t){let n=this.loadStore(),o=l(e);n[o]=t,this.saveStore(n)}async remove(e){let t=this.loadStore(),n=l(e);delete t[n],this.saveStore(t)}async list(){let e=this.loadStore();return Object.keys(e)}loadStore(){if(!ze(X))return{};try{let e=this.getOrCreateKey(),t=Ge(X);if(t.length<P+Ee)return{};let n=t.subarray(0,P),o=t.subarray(P,P+Ee),a=t.subarray(P+Ee),i=xn(Ze,e,n);i.setAuthTag(o);let s=Buffer.concat([i.update(a),i.final()]);return JSON.parse(s.toString("utf-8"))}catch{return{}}}saveStore(e){let t=this.getOrCreateKey(),n=qe(P),o=En(Ze,t,n),a=Buffer.from(JSON.stringify(e),"utf-8"),i=Buffer.concat([o.update(a),o.final()]),s=o.getAuthTag(),c=Buffer.concat([n,s,i]);We(Ye(X),{recursive:!0}),Je(X,c,{mode:384})}getOrCreateKey(){if(ze($)){let t=Ge($);if(t.length!==Re)throw new Error(`Credential keyring key is corrupted (expected ${Re} bytes, got ${t.length}). Delete ${$} and re-authenticate.`);return t}let e=qe(Re);return We(Ye($),{recursive:!0}),Je($,e,{mode:384}),e}};import{execFile as vn}from"child_process";import{promisify as Kn}from"util";var $n=Kn(vn),Qe=3e4,A=class{constructor(e){this.helperPath=e}helperPath;async get(e){let t=l(e);try{let o=(await this.runHelper("get",{publisher:t})).trim();return o?JSON.parse(o):null}catch(n){throw new Error(`Credential helper '${this.helperPath}' failed to read credential for '${t}': ${Q(n)}
90
+ "@`,wn="";import{execFile as Sn,spawn as Rn}from"child_process";import{promisify as En}from"util";var q=En(Sn),vn="kanonak",w=class{constructor(e=vn){this.service=e}service;async get(e){let t=l(e);try{let{stdout:n}=await q("secret-tool",["lookup","service",this.service,"publisher",t],{timeout:1e4}),o=n.trim();return o?JSON.parse(o):null}catch{return null}}async store(e,t){let n=l(e),o=JSON.stringify(t);await new Promise((i,a)=>{let s=Rn("secret-tool",["store","--label",`Kanonak: ${n}`,"service",this.service,"publisher",n],{stdio:["pipe","ignore","ignore"],timeout:1e4});s.stdin.write(o),s.stdin.end(),s.on("close",c=>{c===0?i():a(new Error(`secret-tool store exited with code ${c}`))}),s.on("error",a)})}async remove(e){let t=l(e);try{await q("secret-tool",["clear","service",this.service,"publisher",t],{timeout:1e4})}catch{}}async list(){try{let{stdout:e}=await q("secret-tool",["search","service",this.service],{timeout:1e4}),t=[];for(let n of e.split(`
91
+ `)){let o=n.match(/attribute\.publisher\s*=\s*(.+)/);o&&t.push(o[1].trim())}return t}catch{return[]}}};async function j(){try{return await q("sh",["-c","command -v secret-tool"],{timeout:5e3}),!0}catch{return!1}}import{existsSync as Me,mkdirSync as He,readFileSync as ze,writeFileSync as We}from"fs";import{createCipheriv as Cn,createDecipheriv as xn,randomBytes as Ge}from"crypto";import{homedir as In}from"os";import{join as Re,dirname as Je}from"path";var Ye=Re(In(),".config","kanonak"),T=Re(Ye,"keyring.key"),Kn=Re(Ye,"credentials.enc"),qe="aes-256-gcm",we=32,E=12,Se=16,S=class{constructor(e=Kn){this.secretsFile=e}secretsFile;async get(e){let t=this.loadStore(),n=l(e);return t[n]??null}async store(e,t){let n=this.loadStore(),o=l(e);n[o]=t,this.saveStore(n)}async remove(e){let t=this.loadStore(),n=l(e);delete t[n],this.saveStore(t)}async list(){let e=this.loadStore();return Object.keys(e)}loadStore(){if(!Me(this.secretsFile))return{};try{let e=this.getOrCreateKey(),t=ze(this.secretsFile);if(t.length<E+Se)return{};let n=t.subarray(0,E),o=t.subarray(E,E+Se),i=t.subarray(E+Se),a=xn(qe,e,n);a.setAuthTag(o);let s=Buffer.concat([a.update(i),a.final()]);return JSON.parse(s.toString("utf-8"))}catch{return{}}}saveStore(e){let t=this.getOrCreateKey(),n=Ge(E),o=Cn(qe,t,n),i=Buffer.from(JSON.stringify(e),"utf-8"),a=Buffer.concat([o.update(i),o.final()]),s=o.getAuthTag(),c=Buffer.concat([n,s,a]);He(Je(this.secretsFile),{recursive:!0}),We(this.secretsFile,c,{mode:384})}getOrCreateKey(){if(Me(T)){let t=ze(T);if(t.length!==we)throw new Error(`Credential keyring key is corrupted (expected ${we} bytes, got ${t.length}). Delete ${T} and re-authenticate.`);return t}let e=Ge(we);return He(Je(T),{recursive:!0}),We(T,e,{mode:384}),e}};import{execFile as $n}from"child_process";import{promisify as jn}from"util";var Tn=jn($n),Ze=3e4,A=class{constructor(e){this.helperPath=e}helperPath;async get(e){let t=l(e);try{let o=(await this.runHelper("get",{publisher:t})).trim();return o?JSON.parse(o):null}catch(n){throw new Error(`Credential helper '${this.helperPath}' failed to read credential for '${t}': ${Y(n)}
92
92
  Verify the helper binary exists, is executable, and implements the Kanonak credential helper protocol.
93
- Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,t){let n=l(e);try{await this.runHelper("store",{publisher:n,credential:t})}catch(o){throw new Error(`Credential helper '${this.helperPath}' failed to store credential for '${n}': ${Q(o)}
94
- Verify the helper binary supports the 'store' action.`)}}async remove(e){let t=l(e);try{await this.runHelper("erase",{publisher:t})}catch(n){console.warn(` Warning: Credential helper '${this.helperPath}' failed to erase credential for '${t}': ${Q(n)}`)}}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: ${Q(e)}`),[]}}async runHelper(e,t){try{let{stdout:n}=await $n(this.helperPath,[e],{...t&&{input:JSON.stringify(t)},timeout:Qe});return n}catch(n){throw jn(n)?new Error(`Credential helper not found at '${this.helperPath}'.
95
- Check the 'credentialHelper' path in ~/.kanonak/config.json.`):An(n)?new Error(`Credential helper '${this.helperPath}' timed out after ${Qe/1e3}s on '${e}'.
96
- The helper may be waiting for authentication to an external vault.`):n}}};function Q(r){return r instanceof Error?r.message:String(r)}function jn(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}function An(r){return r instanceof Error&&"killed"in r&&r.killed}var Ie=Tn(Dn(),".kanonak","config.json"),ee=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=Nn(e);if(t)return t;let o=await(await this.getBackend()).get(e);return!o||!F(o)?null:o.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=Bn();return e.credentialHelper?new A(e.credentialHelper):process.platform==="darwin"?new I:process.platform==="win32"?new v:await Se()?new K:new j}};function Nn(r){let t="KANONAK_TOKEN_"+l(r).replace(/[.\-]/g,"_").toUpperCase();return process.env[t]??null}function Bn(){if(!Vn(Ie))return{};try{return JSON.parse(On(Ie,"utf-8"))}catch(r){let e=r instanceof Error?r.message:String(r);return console.warn(` Warning: Failed to parse ${Ie}: ${e}
97
- Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{createHash as Un,createPrivateKey as _n,generateKeyPairSync as Ln,randomUUID as Fn,sign as Mn}from"crypto";function tt(){let{publicKey:r,privateKey:e}=Ln("ec",{namedCurve:"P-256"});return{publicKey:r.export({format:"jwk"}),privateKey:e.export({format:"jwk"})}}function V(r,e,t,n,o,a){let i={alg:"ES256",typ:"dpop+jwt",jwk:{kty:e.kty,crv:e.crv,x:e.x,y:e.y}},s={jti:Fn(),htm:t.toUpperCase(),htu:n,iat:Math.floor(Date.now()/1e3)};return o&&(s.ath=Un("sha256").update(o).digest("base64url")),a&&(s.nonce=a),Hn(i,s,r)}function rt(r){return!r||r.length===0?!1:r.some(e=>e.toUpperCase()==="ES256")}function Hn(r,e,t){let n=et(JSON.stringify(r)),o=et(JSON.stringify(e)),a=`${n}.${o}`,i=_n({key:t,format:"jwk"}),c=Mn("SHA256",Buffer.from(a),{key:i,dsaEncoding:"ieee-p1363"}).toString("base64url");return`${a}.${c}`}function et(r){return Buffer.from(r,"utf-8").toString("base64url")}function nt(r){let e=new Map;return async(t,n,o="GET")=>{if(!r)return b(t,{method:o});let a=await r.getCredential(n);if(!a?.accessToken)return b(t,{method:o});L(a)&&console.warn(` Warning: Access token for '${n}' is expired. Run 'kanonak login ${n}' to re-authenticate.`);let i={};if(a.dpopKeyPair){let c=e.get(n);try{let u=V(a.dpopKeyPair.privateKey,a.dpopKeyPair.publicKey,o,t,a.accessToken,c);i.Authorization=`DPoP ${a.accessToken}`,i.DPoP=u}catch(u){let p=u instanceof Error?u.message:String(u);console.error(` Error: Failed to create DPoP proof for '${n}': ${p}
98
- The stored key pair may be corrupted. Run 'kanonak login ${n}' to re-authenticate.`),i.Authorization=`Bearer ${a.accessToken}`}}else i.Authorization=`Bearer ${a.accessToken}`;let s=await b(t,{method:o,headers:i});if(s.status===401&&a.dpopKeyPair){let c=s.headers.get("DPoP-Nonce");if(c){e.set(n,c);try{let u=V(a.dpopKeyPair.privateKey,a.dpopKeyPair.publicKey,o,t,a.accessToken,c);i.DPoP=u,s=await b(t,{method:o,headers:i})}catch{}}}return s}}import{readFileSync as zn,writeFileSync as Wn,existsSync as Gn}from"fs";import{createHash as Jn}from"crypto";import ot from"js-yaml";var at="kanonak.lock",qn=`# This file is generated by Kanonak CLI. Do not edit manually.
99
- `;function it(r=at){if(!Gn(r))return null;let e=zn(r,"utf-8"),t=ot.load(e);return!t||typeof t!="object"||t.version!=="1"?null:{version:"1",lastUpdated:t.lastUpdated??new Date().toISOString(),packages:t.packages??{}}}function st(r,e=at){r.lastUpdated=new Date().toISOString();let t={};for(let o of Object.keys(r.packages).sort())t[o]=r.packages[o];r.packages=t;let n=ot.dump(r,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Wn(e,qn+n,"utf-8")}function ct(r){return`sha256:${Jn("sha256").update(r).digest("hex")}`}import*as $e from"js-yaml";import{canonicalForm as Yn,canonicalHash as Zn}from"@kanonak-protocol/canonical";function ve(r){return typeof r=="object"&&r!==null&&Array.isArray(r.subjects)}import{CANONICAL_FORM_VERSION as yt}from"@kanonak-protocol/canonical";function lt(r){return Yn(ve(r)?r:ut(r))}function te(r){return Zn(ve(r)?r:ut(r))}function ut(r){let e=[];for(let t of r)t instanceof f&&e.push({uri:to(t),statements:Ke(t.statement)});return{subjects:e}}function Ke(r){let e=[];for(let t of r){let n=eo(t);if(!n)continue;let o=Xn(t);o&&e.push({predicate:n,value:o})}return e}function Xn(r){if(r instanceof pe&&r.carrier)return{lit:r.lexical??String(r.object),datatype:dt(r.carrier)};if(r instanceof de)return{raw:r.object};if(r instanceof me)return{raw:r.lexical??String(r.object)};if(r instanceof fe)return{raw:r.lexical??String(r.object)};if(r instanceof ye)return{ref:mt(r.object)};if(r instanceof ge)return pt(r.object);if(r instanceof ke)return{list:r.object.map(Qn)}}function pt(r){let e=Ke(r.statement);return r.name&&r.name.length>0?{embed:{name:r.name,statements:e}}:{embed:{statements:e}}}function Qn(r){if(r instanceof h)return{ref:mt(r)};if(r instanceof y)return pt(r);if(r instanceof ue){if(r.carrier)return{lit:r.lexical??String(r.value),datatype:dt(r.carrier)};let e=r.value;if(typeof e=="string")return{raw:e};if(typeof e=="number")return{raw:String(e)};if(typeof e=="boolean")return{raw:String(e)}}if(r instanceof le)return{embed:{statements:Ke(r.statement)}};throw new Error(`canonicalForm: list item of unrecognized kind (${r.constructor?.name??typeof r}); add canonicalization support before hashing data that contains it`)}function dt(r){return r===U.LangString?"kanonak.org/core-rdf/langString":`kanonak.org/core-xsd/${r}`}function eo(r){let e=r.predicate;if(e)return ft(e.subject)}function to(r){let e=r.namespace??"",t=r.name??"";return`${e}/${t}`}function mt(r){return ft(r.subject)}function ft(r){let e=r.version;return e&&typeof e.major=="number"?`${r.publisher}/${r.package_}@${e.major}.${e.minor}.${e.patch}/${r.name}`:`${r.publisher}/${r.package_}/${r.name}`}import{VersionOperator as gt}from"@kanonak-protocol/types/document/models/enums";var ro="0.0.0",w=class{constructor(e,t=new S,n){this.repository=e;this.parser=t;this.objectParser=n??new E(this.parser)}repository;parser;objectParser;imports(){return new O}serializeValue(e,t){return bt(e,t)}async buildContentAddressed(e){let t=e.book.toImports(),n=await this.hashBody(e.publisher,t,e.body),o=je(n),a={type:"EphemeralPackage",publisher:e.publisher,imports:t};e.contentHashProperty&&(a[e.contentHashProperty]=n),Object.assign(a,e.header??{}),a.imports=t;let i={[o]:a,...e.body},s=this.dump(i);return{yaml:s,byteCount:ht(s),contentHash:n,packageName:o,publisher:e.publisher,resourceCount:Object.keys(e.body).length}}async buildNamed(e){let t=e.book.toImports(),n={type:e.type??"Package",publisher:e.publisher,version:e.version,imports:t},o;e.contentHashProperty&&(o=await this.hashBody(e.publisher,t,e.body),n[e.contentHashProperty]=o),Object.assign(n,e.header??{}),n.imports=t;let a={[e.name]:n,...e.body},i=this.dump(a),s={yaml:i,byteCount:ht(i),packageName:e.name,publisher:e.publisher,resourceCount:Object.keys(e.body).length};return o!==void 0&&(s.contentHash=o),s}dump(e){return $e.dump(e,{lineWidth:-1})}async hashBody(e,t,n){let o={[kt]:{type:"EphemeralPackage",publisher:e,imports:t},...n},a=this.parser.parse($e.dump(o,{lineWidth:-1})),i=a.metadata.namespace_?.toString(),c=(await this.objectParser.parseKanonaks(new _e(a,this.repository))).filter(u=>u instanceof f&&u.namespace===i&&u.name!==kt);for(let u of c)u.namespace="ephemeral";return te(c)}},kt="__pkgbuilder_probe__";function ht(r){return new TextEncoder().encode(r).length}function je(r){let e="sha256:",t=r.startsWith(e)?e.length:0;return`q-${r.slice(t,t+16)}`}var O=class{byKey=new Map;aliases=new Set;ensure(e,t,n,o,a=gt.Major){let i=`${e}/${t}@${n}`,s=this.byKey.get(i);if(s)return s.alias;let c=this.uniqueAlias(o);return this.byKey.set(i,{publisher:e,package_:t,version:n,alias:c,match:a}),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_,k(e.version),e.package_)}.${e.name}`}refLatest(e,t,n,o){return`${this.ensure(e,t,ro,o??t,gt.Any)}.${n}`}toImports(){let e=new Map;for(let n of this.byKey.values()){let o=e.get(n.publisher)??[];o.push(n),e.set(n.publisher,o)}return[...e.keys()].sort().map(n=>({publisher:n,packages:e.get(n).sort((o,a)=>o.package_<a.package_?-1:1).map(o=>({package:o.package_,match:ce(o.match),version:o.version,alias:o.alias}))}))}uniqueAlias(e){let t=D(e)||"pkg",n=t,o=2;for(;this.aliases.has(n);)n=`${t}${o++}`;return this.aliases.add(n),n}};function bt(r,e){if(r!=null){if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return r;if(r instanceof h)return e.ref(r.subject);if(Array.isArray(r)){let t=r.map(n=>bt(n,e)).filter(n=>n!==void 0);return t.length>0?t:void 0}if(r instanceof y)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(no(r))throw new Error(`Value produced a bare URI without a version (${r.publisher}/${r.package_}/${r.name}); cannot serialize it as a reference.`)}}function D(r){return r.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function no(r){return typeof r=="object"&&r!==null&&typeof r.publisher=="string"&&typeof r.package_=="string"&&typeof r.name=="string"}var re=class{constructor(e){this.producers=e}producers;produced=new Map;producerFor(e,t){return this.producers.find(n=>n.canProduce(e,t))}async produceCached(e,t,n,o){let a=`${t}/${n}@${k(o)}`,i=this.produced.get(a);if(i)return i;let{document:s}=await e.produce(t,n,o);return this.produced.set(a,s),s}async getHighestCompatibleVersionAsync(e,t){let n=this.producerFor(e,t.packageName);if(!n)return null;let o={operator:t.versionOperator,version:t.version},a=await n.resolveVersion(e,t.packageName,o);return a?this.produceCached(n,e,t.packageName,a):null}async getDocumentAsync(e){let t;try{t=be(e)}catch{return null}if(t.kind!=="package"||!t.version)return null;let n=this.producerFor(t.publisher,t.package_);return n?this.produceCached(n,t.publisher,t.package_,t.version):null}async getDocumentsByNamespaceAsync(e,t){return Array.from(this.produced.values()).filter(n=>{let o=n.metadata.namespace_;return o!=null&&o.publisher===e&&o.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 Ae={async authorize(){return{allowed:!0}}},Ve={async record(){}},T=class extends Error{constructor(t,n){let o=`${t.publisher}/${t.package_}${t.version?`@${t.version.major}.${t.version.minor}.${t.version.patch}`:""}`;super(`Not entitled to produce ${o}${n?`: ${n}`:""}`);this.address=t;this.reason=n;this.name="EntitlementDeniedError"}address;reason},ne=class{inner;ctx;policy;meter;constructor(e,t,n=Ae,o=Ve){this.inner=e,this.ctx=t,this.policy=n,this.meter=o}canProduce(e,t){return this.inner.canProduce(e,t)}async resolveVersion(e,t,n){return await this.assertAllowed({publisher:e,package_:t,version:n.version}),this.inner.resolveVersion(e,t,n)}async produce(e,t,n){let o={publisher:e,package_:t,version:n};await this.assertAllowed(o);let a=await this.inner.produce(e,t,n);return await this.meter.record(this.ctx,o,a),a}async assertAllowed(e){let t=await this.policy.authorize(this.ctx,e);if(!t.allowed)throw new T(e,t.reason)}};var d="kanonak.org",m="view",Pt="core-kanonak",oo={publisher:d,package_:m,name:"rootView"},ao={publisher:d,package_:m,name:"bind"},io={publisher:d,package_:m,name:"produces"},so={publisher:d,package_:m,name:"projections"},co={publisher:d,package_:m,name:"where"},lo={publisher:d,package_:m,name:"value"},uo={publisher:d,package_:m,name:"as"},oe=class{constructor(e,t=new S){this.repository=e;this.parser=t;this.objectParser=new E(this.parser),this.builder=new w(this.repository,this.parser,this.objectParser)}repository;parser;objectParser;builder;async materialize(e,t={}){let n=await this.objectParser.parseKanonaks(this.repository),o=this.resolveView(n,e),a=x(o,ao);if(!a)throw new Error(`View ${o.namespace}/${o.name} declares no view.bind; cannot materialize.`);let i=x(o,io);if(!i)throw new Error(`View ${o.namespace}/${o.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 s=po(o),c=wt(n,d,Pt),u=wt(n,d,m),p=this.builder.imports(),ae=p.ensure(d,Pt,c,"ck"),St=p.ensure(d,m,u,"v"),Rt=p.ref(i),Et=new Me(this.repository,this.parser,this.objectParser),Oe=new Le(Et,n),xt=this.readProjections(n,o),It=yo(o,co),vt=this.findInstances(n,a,await this.reason(t)),De={},Kt=new Set;for(let N of vt){if(!await this.passesWhere(Oe,n,It,N))continue;let se={type:Rt};for(let Ne of xt){let $t=await this.evaluateValue(Oe,n,Ne.value,N),Be=this.builder.serializeValue(Ct($t),p);Be!==void 0&&(se[p.ref(Ne.as)]=Be)}let Te=g(N);Te&&(se[`${St}.derivedFrom`]=p.ref(Te)),De[this.rowName(N,Kt)]=se}let ie={};t.resolvedAt&&(ie[`${ae}.resolvedAt`]=t.resolvedAt),t.invocationId&&(ie[`${ae}.id`]=t.invocationId);let C=await this.builder.buildContentAddressed({publisher:s,book:p,body:De,contentHashProperty:`${ae}.contentHash`,header:ie});return{yaml:C.yaml,contentHash:C.contentHash,packageName:C.packageName,publisher:C.publisher,rowCount:C.resourceCount}}resolveView(e,t){let n=_(e,t);if(!n)throw new Error(`View ${t.publisher}/${t.package_}/${t.name} not found in the catalog.`);let o=x(n,oo);if(o){let a=_(e,o);if(!a)throw new Error(`ViewPackage ${t.name} names rootView ${o.name}, which is not in the catalog.`);return a}return n}readProjections(e,t){let n=[];for(let o of we(t,so)){let a=o instanceof y?o:o instanceof h?_(e,o.subject):void 0;if(!a)continue;let i=Pe(a,lo),s=x(a,uo);i&&s&&n.push({value:i,as:s})}return n}async reason(e){return new he({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,t,n){let o=fo(e),a=[],i=new Set;for(let s of n.getInstancesOfClass(t)){if(i.has(s))continue;i.add(s);let c=o.get(s);c&&a.push(c)}return a.sort((s,c)=>{let u=R(g(s)),p=R(g(c));return u<p?-1:u>p?1:0}),a}async passesWhere(e,t,n,o){for(let a of n){let i=await this.evaluateValue(e,t,a,o);if(!go(i))return!1}return!0}async evaluateValue(e,t,n,o){let a=Fe(n,"view-projection",{catalog:t,depth:0}),i=new Map([["input",o]]);return e.evaluate(a,i)}rowName(e,t){let n=D(e.name)||"row",o=n,a=2;for(;t.has(o);)o=`${n}-${a++}`;return t.add(o),o}};function Ct(r){return Ce(r)?r.value:Array.isArray(r)?r.map(Ct):r}function po(r){let e=g(r);if(!e)throw new Error(`Could not derive a publisher from view ${r.namespace}/${r.name}.`);return e.publisher}function wt(r,e,t){let n=mo(r,e,t);if(!n)throw new Error(`Package ${e}/${t} is not in the catalog; it must be importable to materialize a view.`);return n}function mo(r,e,t){let n;for(let o of r){if(!(o instanceof f))continue;let a=g(o);!a||a.publisher!==e||a.package_!==t||!a.version||(!n||B(a.version,n)>0)&&(n=a.version)}return n?k(n):void 0}function fo(r){let e=new Map,t=new Map;for(let n of r){if(!(n instanceof f))continue;let o=g(n);if(!o||!o.version)continue;let a=R(o),i=t.get(a);(!i||B(o.version,i)>0)&&(t.set(a,o.version),e.set(a,n))}return e}function yo(r,e){let t=Pe(r,e);return t?[t]:we(r,e).filter(n=>n instanceof y)}function go(r){return r===!0?!0:r===!1||r===void 0||r===null?!1:typeof r=="string"?r.length>0:typeof r=="number"?r!==0:Ce(r)?r.value.length>0:Array.isArray(r)?r.length>0:!!r}export{rn as AmbiguousReferenceRule,fe as BooleanStatement,yt as CANONICAL_FORM_VERSION,U as Carrier,ln as ClassDefinitionRule,Gr as ClassHierarchyCycleRule,Lt as CompositeKanonakDocumentRepository,ee as CredentialStore,le as DefinedKanonak,en as DefinitionPropertyReferenceRule,_t as DocumentLocation,yr as EdgeType,y as EmbeddedKanonak,Hr as EmbeddedKanonakTypeRule,ge as EmbeddedStatement,T as EntitlementDeniedError,ne as EntitlementProducer,Ut as FileSystemKanonakDocumentRepository,wr as GitIgnoreFilter,gr as GraphBuilder,Yt as HttpKanonakDocumentRepository,O as ImportBook,zr as ImportExistenceRule,Bt as InMemoryKanonakDocumentRepository,Ht as KANONAK_USER_AGENT,tr as Kanonak,Sr as KanonakDocumentPositions,E as KanonakObjectParser,pn as KanonakObjectValidator,S as KanonakParser,rr as KanonakUri,xr as KanonakUriBuilder,vr as KanonakUrlResolver,ur as KanonakVocabulary,ke as ListStatement,ue as LiteralKanonak,Zt as LocalFirstRepository,Xt as LockAwareRepository,fn as LookRenderer,un as MarkdownLinkRule,or as MarkdownStatement,Xr as NamespaceImportCycleRule,Ur as NamespacePrefixRule,fr as NodeType,me as NumberStatement,br as OWL_RL_CLASSIFICATION_RULES,on as ObjectPropertyImportRule,an as ObjectPropertyValueValidationRule,Tr as OntologyValidationError,Or as OntologyValidationResult,w as PackageBuilder,Mr as PackageHeaderRule,re as ProducerRepository,sn as PropertyDomainRule,Jr as PropertyHierarchyCycleRule,Cr as PropertyMetadata,nn as PropertyRangeReferenceRule,qr as PropertyRangeRequiredRule,Lr as PropertyTypeSpecificityRule,cn as PropertyValueTypeRule,Gt as PublisherConfigResolver,Jt as PublisherIndex,hr as RDFS_RULES,he as Reasoner,Pr as ReasoningResult,h as ReferenceKanonak,ye as ReferenceStatement,Mt as RepositoryFactory,_r as ResourceNamingRule,ar as ResourceResolver,mr as ResourceTypeClassifier,pe as ScalarStatement,nr as Statement,de as StringStatement,Yr as SubClassOfReferenceRule,Zr as SubPropertyOfReferenceRule,f as SubjectKanonak,Fr as SubjectKanonakTypeRequiredRule,kr as TripleStore,ir as TypeResolver,Qr as UnresolvedPredicateRule,Wr as UnresolvedReferenceRule,Br as ValidationCache,Nr as ValidationContext,Dr as ValidationSeverity,Si as VersionOperator,oe as ViewMaterializer,tn as XsdImportRule,Ae as allowAllPolicy,qt as assertPackageIdentity,er as buildLocalFirstRepository,yn as buildOntologyModel,lt as canonicalForm,te as canonicalHash,Ue as carrierOf,Qt as collectKanonakFiles,B as compareVersions,ct as computeIntegrity,je as contentAddressedName,Ar as contextTypesOf,nt as createAuthenticatedFetch,V as createDPoPProof,Vt as createVersion,dr as extractMarkdownLinks,dn as findDerivation,Vr as findInstancesByType,pr as findMalformedReferences,Er as findMarkdownLinkAt,Ir as formatKanonakAddress,k as formatVersion,tt as generateDPoPKeyPair,Ft as getGlobalCachePath,Wt as getKanonakUserAgent,F as hasValidToken,Dt as isCompatibleVersion,L as isExpired,Tt as isMajorCompatible,b as kanonakFetch,it as loadLockFile,sr as makeUriKey,Ve as noopMeter,l as normalizeHost,be as parseKanonakAddress,Ot as parseVersionString,Rr as parseWithPositions,Nt as pickHighestDocument,$r as propertiesInScope,mn as resolveDisplayValue,jr as resolvePropertyStep,D as sanitizeName,st as saveLockFile,rt as serverSupportsDPoP,zt as setKanonakUserAgent,g as subjectUri,Kr as superClassChain,cr as tripleKey,R as uriKey,lr as uriTriple,jt as versionOperatorFromChar,ce as versionOperatorToChar,At as versionsEqual};
93
+ Check the 'credentialHelper' path in ~/.kanonak/config.json.`)}}async store(e,t){let n=l(e);try{await this.runHelper("store",{publisher:n,credential:t})}catch(o){throw new Error(`Credential helper '${this.helperPath}' failed to store credential for '${n}': ${Y(o)}
94
+ Verify the helper binary supports the 'store' action.`)}}async remove(e){let t=l(e);try{await this.runHelper("erase",{publisher:t})}catch(n){console.warn(` Warning: Credential helper '${this.helperPath}' failed to erase credential for '${t}': ${Y(n)}`)}}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: ${Y(e)}`),[]}}async runHelper(e,t){try{let{stdout:n}=await Tn(this.helperPath,[e],{...t&&{input:JSON.stringify(t)},timeout:Ze});return n}catch(n){throw An(n)?new Error(`Credential helper not found at '${this.helperPath}'.
95
+ Check the 'credentialHelper' path in ~/.kanonak/config.json.`):Dn(n)?new Error(`Credential helper '${this.helperPath}' timed out after ${Ze/1e3}s on '${e}'.
96
+ The helper may be waiting for authentication to an external vault.`):n}}};function Y(r){return r instanceof Error?r.message:String(r)}function An(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}function Dn(r){return r instanceof Error&&"killed"in r&&r.killed}var Ee=Nn(On(),".kanonak","config.json"),Z=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=_n(e);if(t)return t;let o=await(await this.getBackend()).get(e);return!o||!M(o)?null:o.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=Un();return e.credentialHelper?new A(e.credentialHelper):process.platform==="darwin"?new b:process.platform==="win32"?new P:await j()?new w:new S}};function _n(r){let t="KANONAK_TOKEN_"+l(r).replace(/[.\-]/g,"_").toUpperCase();return process.env[t]??null}function Un(){if(!Vn(Ee))return{};try{return JSON.parse(Bn(Ee,"utf-8"))}catch(r){let e=r instanceof Error?r.message:String(r);return console.warn(` Warning: Failed to parse ${Ee}: ${e}
97
+ Using default credential backend. Fix the JSON syntax or delete the file.`),{}}}import{homedir as Fn}from"os";import{join as Ln}from"path";var ve="kanonak-device",Mn=Ln(Fn(),".config","kanonak","device-credentials.enc"),X=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 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 process.platform==="darwin"?new b(ve):process.platform==="win32"?new P(`${ve}:`):await j()?new w(ve):new S(Mn)}};import{createHash as Hn,createPrivateKey as zn,generateKeyPairSync as Wn,randomUUID as Gn,sign as Jn}from"crypto";function Qe(){let{publicKey:r,privateKey:e}=Wn("ec",{namedCurve:"P-256"});return{publicKey:r.export({format:"jwk"}),privateKey:e.export({format:"jwk"})}}function D(r,e,t,n,o,i){let a={alg:"ES256",typ:"dpop+jwt",jwk:{kty:e.kty,crv:e.crv,x:e.x,y:e.y}},s={jti:Gn(),htm:t.toUpperCase(),htu:n,iat:Math.floor(Date.now()/1e3)};return o&&(s.ath=Hn("sha256").update(o).digest("base64url")),i&&(s.nonce=i),qn(a,s,r)}function et(r){return!r||r.length===0?!1:r.some(e=>e.toUpperCase()==="ES256")}function qn(r,e,t){let n=Xe(JSON.stringify(r)),o=Xe(JSON.stringify(e)),i=`${n}.${o}`,a=zn({key:t,format:"jwk"}),c=Jn("SHA256",Buffer.from(i),{key:a,dsaEncoding:"ieee-p1363"}).toString("base64url");return`${i}.${c}`}function Xe(r){return Buffer.from(r,"utf-8").toString("base64url")}function tt(r){let e=new Map;return async(t,n,o="GET")=>{if(!r)return R(t,{method:o});let i=await r.getCredential(n);if(!i?.accessToken)return R(t,{method:o});L(i)&&console.warn(` Warning: Access token for '${n}' is expired. Run 'kanonak login ${n}' to re-authenticate.`);let a={};if(i.dpopKeyPair){let c=e.get(n);try{let u=D(i.dpopKeyPair.privateKey,i.dpopKeyPair.publicKey,o,t,i.accessToken,c);a.Authorization=`DPoP ${i.accessToken}`,a.DPoP=u}catch(u){let p=u instanceof Error?u.message:String(u);console.error(` Error: Failed to create DPoP proof for '${n}': ${p}
98
+ The stored key pair may be corrupted. Run 'kanonak login ${n}' to re-authenticate.`),a.Authorization=`Bearer ${i.accessToken}`}}else a.Authorization=`Bearer ${i.accessToken}`;let s=await R(t,{method:o,headers:a});if(s.status===401&&i.dpopKeyPair){let c=s.headers.get("DPoP-Nonce");if(c){e.set(n,c);try{let u=D(i.dpopKeyPair.privateKey,i.dpopKeyPair.publicKey,o,t,i.accessToken,c);a.DPoP=u,s=await R(t,{method:o,headers:a})}catch{}}}return s}}import{readFileSync as Yn,writeFileSync as Zn,existsSync as Xn}from"fs";import{createHash as Qn}from"crypto";import rt from"js-yaml";var nt="kanonak.lock",eo=`# This file is generated by Kanonak CLI. Do not edit manually.
99
+ `;function ot(r=nt){if(!Xn(r))return null;let e=Yn(r,"utf-8"),t=rt.load(e);return!t||typeof t!="object"||t.version!=="1"?null:{version:"1",lastUpdated:t.lastUpdated??new Date().toISOString(),packages:t.packages??{}}}function it(r,e=nt){r.lastUpdated=new Date().toISOString();let t={};for(let o of Object.keys(r.packages).sort())t[o]=r.packages[o];r.packages=t;let n=rt.dump(r,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Zn(e,eo+n,"utf-8")}function at(r){return`sha256:${Qn("sha256").update(r).digest("hex")}`}import*as Ie from"js-yaml";import{canonicalForm as to,canonicalHash as ro}from"@kanonak-protocol/canonical";function Ce(r){return typeof r=="object"&&r!==null&&Array.isArray(r.subjects)}import{CANONICAL_FORM_VERSION as mt}from"@kanonak-protocol/canonical";function st(r){return to(Ce(r)?r:ct(r))}function Q(r){return ro(Ce(r)?r:ct(r))}function ct(r){let e=[];for(let t of r)t instanceof f&&e.push({uri:ao(t),statements:xe(t.statement)});return{subjects:e}}function xe(r){let e=[];for(let t of r){let n=io(t);if(!n)continue;let o=no(t);o&&e.push({predicate:n,value:o})}return e}function no(r){if(r instanceof le&&r.carrier)return{lit:r.lexical??String(r.object),datatype:ut(r.carrier)};if(r instanceof ue)return{raw:r.object};if(r instanceof pe)return{raw:r.lexical??String(r.object)};if(r instanceof de)return{raw:r.lexical??String(r.object)};if(r instanceof me)return{ref:pt(r.object)};if(r instanceof fe)return lt(r.object);if(r instanceof ye)return{list:r.object.map(oo)}}function lt(r){let e=xe(r.statement);return r.name&&r.name.length>0?{embed:{name:r.name,statements:e}}:{embed:{statements:e}}}function oo(r){if(r instanceof h)return{ref:pt(r)};if(r instanceof y)return lt(r);if(r instanceof ce){if(r.carrier)return{lit:r.lexical??String(r.value),datatype:ut(r.carrier)};let e=r.value;if(typeof e=="string")return{raw:e};if(typeof e=="number")return{raw:String(e)};if(typeof e=="boolean")return{raw:String(e)}}if(r instanceof se)return{embed:{statements:xe(r.statement)}};throw new Error(`canonicalForm: list item of unrecognized kind (${r.constructor?.name??typeof r}); add canonicalization support before hashing data that contains it`)}function ut(r){return r===U.LangString?"kanonak.org/core-rdf/langString":`kanonak.org/core-xsd/${r}`}function io(r){let e=r.predicate;if(e)return dt(e.subject)}function ao(r){let e=r.namespace??"",t=r.name??"";return`${e}/${t}`}function pt(r){return dt(r.subject)}function dt(r){let e=r.version;return e&&typeof e.major=="number"?`${r.publisher}/${r.package_}@${e.major}.${e.minor}.${e.patch}/${r.name}`:`${r.publisher}/${r.package_}/${r.name}`}import{VersionOperator as ft}from"@kanonak-protocol/types/document/models/enums";var so="0.0.0",v=class{constructor(e,t=new x,n){this.repository=e;this.parser=t;this.objectParser=n??new K(this.parser)}repository;parser;objectParser;imports(){return new V}serializeValue(e,t){return kt(e,t)}async buildContentAddressed(e){let t=e.book.toImports(),n=await this.hashBody(e.publisher,t,e.body),o=Ke(n),i={type:"EphemeralPackage",publisher:e.publisher,imports:t};e.contentHashProperty&&(i[e.contentHashProperty]=n),Object.assign(i,e.header??{}),i.imports=t;let a={[o]:i,...e.body},s=this.dump(a);return{yaml:s,byteCount:gt(s),contentHash:n,packageName:o,publisher:e.publisher,resourceCount:Object.keys(e.body).length}}async buildNamed(e){let t=e.book.toImports(),n={type:e.type??"Package",publisher:e.publisher,version:e.version,imports:t},o;e.contentHashProperty&&(o=await this.hashBody(e.publisher,t,e.body),n[e.contentHashProperty]=o),Object.assign(n,e.header??{}),n.imports=t;let i={[e.name]:n,...e.body},a=this.dump(i),s={yaml:a,byteCount:gt(a),packageName:e.name,publisher:e.publisher,resourceCount:Object.keys(e.body).length};return o!==void 0&&(s.contentHash=o),s}dump(e){return Ie.dump(e,{lineWidth:-1})}async hashBody(e,t,n){let o={[yt]:{type:"EphemeralPackage",publisher:e,imports:t},...n},i=this.parser.parse(Ie.dump(o,{lineWidth:-1})),a=i.metadata.namespace_?.toString(),c=(await this.objectParser.parseKanonaks(new Ne(i,this.repository))).filter(u=>u instanceof f&&u.namespace===a&&u.name!==yt);for(let u of c)u.namespace="ephemeral";return Q(c)}},yt="__pkgbuilder_probe__";function gt(r){return new TextEncoder().encode(r).length}function Ke(r){let e="sha256:",t=r.startsWith(e)?e.length:0;return`q-${r.slice(t,t+16)}`}var V=class{byKey=new Map;aliases=new Set;ensure(e,t,n,o,i=ft.Major){let a=`${e}/${t}@${n}`,s=this.byKey.get(a);if(s)return s.alias;let c=this.uniqueAlias(o);return this.byKey.set(a,{publisher:e,package_:t,version:n,alias:c,match:i}),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_,k(e.version),e.package_)}.${e.name}`}refLatest(e,t,n,o){return`${this.ensure(e,t,so,o??t,ft.Any)}.${n}`}toImports(){let e=new Map;for(let n of this.byKey.values()){let o=e.get(n.publisher)??[];o.push(n),e.set(n.publisher,o)}return[...e.keys()].sort().map(n=>({publisher:n,packages:e.get(n).sort((o,i)=>o.package_<i.package_?-1:1).map(o=>({package:o.package_,match:ae(o.match),version:o.version,alias:o.alias}))}))}uniqueAlias(e){let t=B(e)||"pkg",n=t,o=2;for(;this.aliases.has(n);)n=`${t}${o++}`;return this.aliases.add(n),n}};function kt(r,e){if(r!=null){if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return r;if(r instanceof h)return e.ref(r.subject);if(Array.isArray(r)){let t=r.map(n=>kt(n,e)).filter(n=>n!==void 0);return t.length>0?t:void 0}if(r instanceof y)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(co(r))throw new Error(`Value produced a bare URI without a version (${r.publisher}/${r.package_}/${r.name}); cannot serialize it as a reference.`)}}function B(r){return r.replace(/[^A-Za-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function co(r){return typeof r=="object"&&r!==null&&typeof r.publisher=="string"&&typeof r.package_=="string"&&typeof r.name=="string"}var ee=class{constructor(e){this.producers=e}producers;produced=new Map;producerFor(e,t){return this.producers.find(n=>n.canProduce(e,t))}async produceCached(e,t,n,o){let i=`${t}/${n}@${k(o)}`,a=this.produced.get(i);if(a)return a;let{document:s}=await e.produce(t,n,o);return this.produced.set(i,s),s}async getHighestCompatibleVersionAsync(e,t){let n=this.producerFor(e,t.packageName);if(!n)return null;let o={operator:t.versionOperator,version:t.version},i=await n.resolveVersion(e,t.packageName,o);return i?this.produceCached(n,e,t.packageName,i):null}async getDocumentAsync(e){let t;try{t=ke(e)}catch{return null}if(t.kind!=="package"||!t.version)return null;let n=this.producerFor(t.publisher,t.package_);return n?this.produceCached(n,t.publisher,t.package_,t.version):null}async getDocumentsByNamespaceAsync(e,t){return Array.from(this.produced.values()).filter(n=>{let o=n.metadata.namespace_;return o!=null&&o.publisher===e&&o.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 $e={async authorize(){return{allowed:!0}}},je={async record(){}},O=class extends Error{constructor(t,n){let o=`${t.publisher}/${t.package_}${t.version?`@${t.version.major}.${t.version.minor}.${t.version.patch}`:""}`;super(`Not entitled to produce ${o}${n?`: ${n}`:""}`);this.address=t;this.reason=n;this.name="EntitlementDeniedError"}address;reason},te=class{inner;ctx;policy;meter;constructor(e,t,n=$e,o=je){this.inner=e,this.ctx=t,this.policy=n,this.meter=o}canProduce(e,t){return this.inner.canProduce(e,t)}async resolveVersion(e,t,n){return await this.assertAllowed({publisher:e,package_:t,version:n.version}),this.inner.resolveVersion(e,t,n)}async produce(e,t,n){let o={publisher:e,package_:t,version:n};await this.assertAllowed(o);let i=await this.inner.produce(e,t,n);return await this.meter.record(this.ctx,o,i),i}async assertAllowed(e){let t=await this.policy.authorize(this.ctx,e);if(!t.allowed)throw new O(e,t.reason)}};var d="kanonak.org",m="view",ht="core-kanonak",lo={publisher:d,package_:m,name:"rootView"},uo={publisher:d,package_:m,name:"bind"},po={publisher:d,package_:m,name:"produces"},mo={publisher:d,package_:m,name:"projections"},fo={publisher:d,package_:m,name:"where"},yo={publisher:d,package_:m,name:"value"},go={publisher:d,package_:m,name:"as"},re=class{constructor(e,t=new x){this.repository=e;this.parser=t;this.objectParser=new K(this.parser),this.builder=new v(this.repository,this.parser,this.objectParser)}repository;parser;objectParser;builder;async materialize(e,t={}){let n=await this.objectParser.parseKanonaks(this.repository),o=this.resolveView(n,e),i=$(o,uo);if(!i)throw new Error(`View ${o.namespace}/${o.name} declares no view.bind; cannot materialize.`);let a=$(o,po);if(!a)throw new Error(`View ${o.namespace}/${o.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 s=ko(o),c=bt(n,d,ht),u=bt(n,d,m),p=this.builder.imports(),ne=p.ensure(d,ht,c,"ck"),wt=p.ensure(d,m,u,"v"),St=p.ref(a),Rt=new Fe(this.repository,this.parser,this.objectParser),Te=new _e(Rt,n),Et=this.readProjections(n,o),vt=Po(o,fo),Ct=this.findInstances(n,i,await this.reason(t)),Ae={},xt=new Set;for(let N of Ct){if(!await this.passesWhere(Te,n,vt,N))continue;let ie={type:St};for(let Ve of Et){let It=await this.evaluateValue(Te,n,Ve.value,N),Be=this.builder.serializeValue(Pt(It),p);Be!==void 0&&(ie[p.ref(Ve.as)]=Be)}let De=g(N);De&&(ie[`${wt}.derivedFrom`]=p.ref(De)),Ae[this.rowName(N,xt)]=ie}let oe={};t.resolvedAt&&(oe[`${ne}.resolvedAt`]=t.resolvedAt),t.invocationId&&(oe[`${ne}.id`]=t.invocationId);let C=await this.builder.buildContentAddressed({publisher:s,book:p,body:Ae,contentHashProperty:`${ne}.contentHash`,header:oe});return{yaml:C.yaml,contentHash:C.contentHash,packageName:C.packageName,publisher:C.publisher,rowCount:C.resourceCount}}resolveView(e,t){let n=F(e,t);if(!n)throw new Error(`View ${t.publisher}/${t.package_}/${t.name} not found in the catalog.`);let o=$(n,lo);if(o){let i=F(e,o);if(!i)throw new Error(`ViewPackage ${t.name} names rootView ${o.name}, which is not in the catalog.`);return i}return n}readProjections(e,t){let n=[];for(let o of be(t,mo)){let i=o instanceof y?o:o instanceof h?F(e,o.subject):void 0;if(!i)continue;let a=he(i,yo),s=$(i,go);a&&s&&n.push({value:a,as:s})}return n}async reason(e){return new ge({profile:e.reasoningProfile??"owl-rl-classification"}).reason(this.repository)}findInstances(e,t,n){let o=bo(e),i=[],a=new Set;for(let s of n.getInstancesOfClass(t)){if(a.has(s))continue;a.add(s);let c=o.get(s);c&&i.push(c)}return i.sort((s,c)=>{let u=I(g(s)),p=I(g(c));return u<p?-1:u>p?1:0}),i}async passesWhere(e,t,n,o){for(let i of n){let a=await this.evaluateValue(e,t,i,o);if(!wo(a))return!1}return!0}async evaluateValue(e,t,n,o){let i=Ue(n,"view-projection",{catalog:t,depth:0}),a=new Map([["input",o]]);return e.evaluate(i,a)}rowName(e,t){let n=B(e.name)||"row",o=n,i=2;for(;t.has(o);)o=`${n}-${i++}`;return t.add(o),o}};function Pt(r){return Pe(r)?r.value:Array.isArray(r)?r.map(Pt):r}function ko(r){let e=g(r);if(!e)throw new Error(`Could not derive a publisher from view ${r.namespace}/${r.name}.`);return e.publisher}function bt(r,e,t){let n=ho(r,e,t);if(!n)throw new Error(`Package ${e}/${t} is not in the catalog; it must be importable to materialize a view.`);return n}function ho(r,e,t){let n;for(let o of r){if(!(o instanceof f))continue;let i=g(o);!i||i.publisher!==e||i.package_!==t||!i.version||(!n||_(i.version,n)>0)&&(n=i.version)}return n?k(n):void 0}function bo(r){let e=new Map,t=new Map;for(let n of r){if(!(n instanceof f))continue;let o=g(n);if(!o||!o.version)continue;let i=I(o),a=t.get(i);(!a||_(o.version,a)>0)&&(t.set(i,o.version),e.set(i,n))}return e}function Po(r,e){let t=he(r,e);return t?[t]:be(r,e).filter(n=>n instanceof y)}function wo(r){return r===!0?!0:r===!1||r===void 0||r===null?!1:typeof r=="string"?r.length>0:typeof r=="number"?r!==0:Pe(r)?r.value.length>0:Array.isArray(r)?r.length>0:!!r}export{en as AmbiguousReferenceRule,de as BooleanStatement,mt as CANONICAL_FORM_VERSION,U as Carrier,sn as ClassDefinitionRule,zr as ClassHierarchyCycleRule,_t as CompositeKanonakDocumentRepository,Z as CredentialStore,se as DefinedKanonak,Xr as DefinitionPropertyReferenceRule,X as DeviceCertificateStore,Nt as DocumentLocation,mr as EdgeType,y as EmbeddedKanonak,Lr as EmbeddedKanonakTypeRule,fe as EmbeddedStatement,O as EntitlementDeniedError,te as EntitlementProducer,Ot as FileSystemKanonakDocumentRepository,br as GitIgnoreFilter,fr as GraphBuilder,Jt as HttpKanonakDocumentRepository,V as ImportBook,Mr as ImportExistenceRule,Bt as InMemoryKanonakDocumentRepository,Lt as KANONAK_USER_AGENT,Qt as Kanonak,wr as KanonakDocumentPositions,K as KanonakObjectParser,ln as KanonakObjectValidator,x as KanonakParser,er as KanonakUri,Er as KanonakUriBuilder,Cr as KanonakUrlResolver,cr as KanonakVocabulary,ye as ListStatement,ce as LiteralKanonak,qt as LocalFirstRepository,Yt as LockAwareRepository,dn as LookRenderer,cn as MarkdownLinkRule,rr as MarkdownStatement,Yr as NamespaceImportCycleRule,Or as NamespacePrefixRule,dr as NodeType,pe as NumberStatement,kr as OWL_RL_CLASSIFICATION_RULES,rn as ObjectPropertyImportRule,nn as ObjectPropertyValueValidationRule,Dr as OntologyValidationError,Tr as OntologyValidationResult,v as PackageBuilder,Fr as PackageHeaderRule,ee as ProducerRepository,on as PropertyDomainRule,Wr as PropertyHierarchyCycleRule,Pr as PropertyMetadata,tn as PropertyRangeReferenceRule,Gr as PropertyRangeRequiredRule,_r as PropertyTypeSpecificityRule,an as PropertyValueTypeRule,zt as PublisherConfigResolver,Wt as PublisherIndex,gr as RDFS_RULES,ge as Reasoner,hr as ReasoningResult,h as ReferenceKanonak,me as ReferenceStatement,Ft as RepositoryFactory,Nr as ResourceNamingRule,nr as ResourceResolver,pr as ResourceTypeClassifier,le as ScalarStatement,tr as Statement,ue as StringStatement,Jr as SubClassOfReferenceRule,qr as SubPropertyOfReferenceRule,f as SubjectKanonak,Ur as SubjectKanonakTypeRequiredRule,yr as TripleStore,or as TypeResolver,Zr as UnresolvedPredicateRule,Hr as UnresolvedReferenceRule,Br as ValidationCache,Vr as ValidationContext,Ar as ValidationSeverity,Oa as VersionOperator,re as ViewMaterializer,Qr as XsdImportRule,$e as allowAllPolicy,Gt as assertPackageIdentity,Xt as buildLocalFirstRepository,mn as buildOntologyModel,st as canonicalForm,Q as canonicalHash,Oe as carrierOf,Zt as collectKanonakFiles,_ as compareVersions,at as computeIntegrity,Ke as contentAddressedName,$r as contextTypesOf,tt as createAuthenticatedFetch,D as createDPoPProof,jt as createVersion,ur as extractMarkdownLinks,un as findDerivation,jr as findInstancesByType,lr as findMalformedReferences,Rr as findMarkdownLinkAt,vr as formatKanonakAddress,k as formatVersion,Qe as generateDPoPKeyPair,Ut as getGlobalCachePath,Ht as getKanonakUserAgent,M as hasValidToken,At as isCompatibleVersion,L as isExpired,Dt as isMajorCompatible,R as kanonakFetch,ot as loadLockFile,ir as makeUriKey,je as noopMeter,l as normalizeHost,ke as parseKanonakAddress,Tt as parseVersionString,Sr as parseWithPositions,Vt as pickHighestDocument,Ir as propertiesInScope,pn as resolveDisplayValue,Kr as resolvePropertyStep,B as sanitizeName,it as saveLockFile,et as serverSupportsDPoP,Mt as setKanonakUserAgent,g as subjectUri,xr as superClassChain,ar as tripleKey,I as uriKey,sr as uriTriple,Kt as versionOperatorFromChar,ae as versionOperatorToChar,$t as versionsEqual};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanonak-protocol/sdk",
3
- "version": "4.12.0",
3
+ "version": "4.13.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": "^4.12.0",
129
+ "@kanonak-protocol/types": "^4.13.0",
130
130
  "ignore": "^7.0.5",
131
131
  "js-yaml": "^4.1.0",
132
132
  "yaml": "^2.7.0"