@kya-os/consent 0.1.44 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/bundle/inline.d.ts.map +1 -1
  2. package/dist/bundle/inline.js +4 -4
  3. package/dist/bundle/inline.js.map +1 -1
  4. package/dist/cjs/bundle/inline.js +4 -4
  5. package/dist/cjs/bundle/inline.js.map +1 -1
  6. package/dist/cjs/components/consent-capabilities-screen.js +52 -12
  7. package/dist/cjs/components/consent-capabilities-screen.js.map +1 -1
  8. package/dist/cjs/components/consent-capability-card.js +191 -32
  9. package/dist/cjs/components/consent-capability-card.js.map +1 -1
  10. package/dist/cjs/components/mcp-consent.js +231 -79
  11. package/dist/cjs/components/mcp-consent.js.map +1 -1
  12. package/dist/cjs/mcp-app/inline.js +2 -2
  13. package/dist/cjs/mcp-app/inline.js.map +1 -1
  14. package/dist/cjs/resolution/credential-capabilities.js +69 -0
  15. package/dist/cjs/resolution/credential-capabilities.js.map +1 -0
  16. package/dist/cjs/security/identity-assertion.js +69 -0
  17. package/dist/cjs/security/identity-assertion.js.map +1 -0
  18. package/dist/cjs/security/index.js +1 -0
  19. package/dist/cjs/security/index.js.map +1 -1
  20. package/dist/components/consent-capabilities-screen.d.ts +32 -0
  21. package/dist/components/consent-capabilities-screen.d.ts.map +1 -1
  22. package/dist/components/consent-capabilities-screen.js +53 -13
  23. package/dist/components/consent-capabilities-screen.js.map +1 -1
  24. package/dist/components/consent-capability-card.d.ts.map +1 -1
  25. package/dist/components/consent-capability-card.js +191 -32
  26. package/dist/components/consent-capability-card.js.map +1 -1
  27. package/dist/components/mcp-consent.d.ts +60 -0
  28. package/dist/components/mcp-consent.d.ts.map +1 -1
  29. package/dist/components/mcp-consent.js +231 -79
  30. package/dist/components/mcp-consent.js.map +1 -1
  31. package/dist/consent.js +486 -167
  32. package/dist/consent.min.js +286 -127
  33. package/dist/mcp-app/inline.d.ts.map +1 -1
  34. package/dist/mcp-app/inline.js +2 -2
  35. package/dist/mcp-app/inline.js.map +1 -1
  36. package/dist/resolution/credential-capabilities.d.ts +38 -0
  37. package/dist/resolution/credential-capabilities.d.ts.map +1 -0
  38. package/dist/resolution/credential-capabilities.js +61 -0
  39. package/dist/resolution/credential-capabilities.js.map +1 -0
  40. package/dist/security/identity-assertion.d.ts +49 -0
  41. package/dist/security/identity-assertion.d.ts.map +1 -0
  42. package/dist/security/identity-assertion.js +66 -0
  43. package/dist/security/identity-assertion.js.map +1 -0
  44. package/dist/security/index.d.ts +1 -0
  45. package/dist/security/index.d.ts.map +1 -1
  46. package/dist/security/index.js +1 -0
  47. package/dist/security/index.js.map +1 -1
  48. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/mcp-app/inline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAW,ws/uBAAws/uB,CAAC;AAErv/uB,4CAA4C;AAC5C,MAAM,CAAC,MAAM,yBAAyB,GAAW,MAAM,CAAC"}
1
+ {"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/mcp-app/inline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAW,m1mvBAAm1mvB,CAAC;AAEh4mvB,4CAA4C;AAC5C,MAAM,CAAC,MAAM,yBAAyB,GAAW,MAAM,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { type AuthMode } from "../types/modes.types.js";
2
+ import type { Capability } from "../types/capabilities.types.js";
3
+ export declare function shouldRenderCapabilityScreen(mode: AuthMode, capabilityCount: number): boolean;
4
+ /**
5
+ * The credential path grants a fixed, all-or-nothing scope set (see the
6
+ * scopes constraint in handleApprove), so every capability starts selected —
7
+ * the rows themselves stay interactive, same as the consent-only path.
8
+ */
9
+ export declare function shouldSelectAllCapabilities(mode: AuthMode): boolean;
10
+ export declare function areCredentialsComplete(formData: Record<string, string>): boolean;
11
+ /**
12
+ * Whether the legacy scope-selection checkboxes (`renderPermissions` /
13
+ * `<consent-permissions>`) should render as interactive. When a signed
14
+ * identity assertion is bound to the request, `handleApprove` always posts
15
+ * the full requested scope set - the assertion binds a hash of that full
16
+ * set, so a user-narrowed subset would fail the mint gate's hash check and
17
+ * 403 (see the comment on the `scopes` form-data append in mcp-consent.ts).
18
+ * Letting the user uncheck a scope that will be granted regardless is a
19
+ * consent-accuracy bug, so this path drops to display-only rows instead.
20
+ * Interactive narrowing returns once the deferred subset-binding follow-up
21
+ * ships.
22
+ */
23
+ export declare function shouldRenderScopesInteractive(identityAssertion: string | undefined): boolean;
24
+ /**
25
+ * Which capabilities count as selected. In disclosure mode every capability is
26
+ * granted, so all ids are returned; otherwise the operator's `defaultOn` seeds
27
+ * the initial selection.
28
+ */
29
+ export declare function capabilityIdsFor(capabilities: Capability[], disclosureMode: boolean): string[];
30
+ /**
31
+ * Identity of a seeding decision: the capability ids in order, plus the
32
+ * all-selected flag. Lit compares properties by reference, so a parent that
33
+ * rebuilds its capability array on every render would otherwise re-seed (and
34
+ * wipe the user's toggles) on every keystroke. Seeding is keyed on this value
35
+ * instead of array identity.
36
+ */
37
+ export declare function capabilitySeedKey(capabilities: Capability[], allSelected: boolean): string;
38
+ //# sourceMappingURL=credential-capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-capabilities.d.ts","sourceRoot":"","sources":["../../src/resolution/credential-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAYjE,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEnE;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAKT;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAC3C,iBAAiB,EAAE,MAAM,GAAG,SAAS,GACpC,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,UAAU,EAAE,EAC1B,cAAc,EAAE,OAAO,GACtB,MAAM,EAAE,CAIV;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,UAAU,EAAE,EAC1B,WAAW,EAAE,OAAO,GACnB,MAAM,CAER"}
@@ -0,0 +1,61 @@
1
+ import { AUTH_MODES } from "../types/modes.types.js";
2
+ /**
3
+ * Modes whose screen is replaced by the humanized capability layout. Credentials
4
+ * is included so the user sees what is being granted before signing in — on the
5
+ * anchor path the sign-in submit IS the approval, so there is no later screen.
6
+ */
7
+ const CAPABILITY_SCREEN_MODES = [
8
+ AUTH_MODES.CONSENT_ONLY,
9
+ AUTH_MODES.CREDENTIALS,
10
+ ];
11
+ export function shouldRenderCapabilityScreen(mode, capabilityCount) {
12
+ return capabilityCount > 0 && CAPABILITY_SCREEN_MODES.includes(mode);
13
+ }
14
+ /**
15
+ * The credential path grants a fixed, all-or-nothing scope set (see the
16
+ * scopes constraint in handleApprove), so every capability starts selected —
17
+ * the rows themselves stay interactive, same as the consent-only path.
18
+ */
19
+ export function shouldSelectAllCapabilities(mode) {
20
+ return mode === AUTH_MODES.CREDENTIALS;
21
+ }
22
+ export function areCredentialsComplete(formData) {
23
+ return ((formData.username?.trim().length ?? 0) > 0 &&
24
+ (formData.password?.trim().length ?? 0) > 0);
25
+ }
26
+ /**
27
+ * Whether the legacy scope-selection checkboxes (`renderPermissions` /
28
+ * `<consent-permissions>`) should render as interactive. When a signed
29
+ * identity assertion is bound to the request, `handleApprove` always posts
30
+ * the full requested scope set - the assertion binds a hash of that full
31
+ * set, so a user-narrowed subset would fail the mint gate's hash check and
32
+ * 403 (see the comment on the `scopes` form-data append in mcp-consent.ts).
33
+ * Letting the user uncheck a scope that will be granted regardless is a
34
+ * consent-accuracy bug, so this path drops to display-only rows instead.
35
+ * Interactive narrowing returns once the deferred subset-binding follow-up
36
+ * ships.
37
+ */
38
+ export function shouldRenderScopesInteractive(identityAssertion) {
39
+ return !identityAssertion;
40
+ }
41
+ /**
42
+ * Which capabilities count as selected. In disclosure mode every capability is
43
+ * granted, so all ids are returned; otherwise the operator's `defaultOn` seeds
44
+ * the initial selection.
45
+ */
46
+ export function capabilityIdsFor(capabilities, disclosureMode) {
47
+ return capabilities
48
+ .filter((capability) => disclosureMode || capability.defaultOn)
49
+ .map((capability) => capability.id);
50
+ }
51
+ /**
52
+ * Identity of a seeding decision: the capability ids in order, plus the
53
+ * all-selected flag. Lit compares properties by reference, so a parent that
54
+ * rebuilds its capability array on every render would otherwise re-seed (and
55
+ * wipe the user's toggles) on every keystroke. Seeding is keyed on this value
56
+ * instead of array identity.
57
+ */
58
+ export function capabilitySeedKey(capabilities, allSelected) {
59
+ return `${allSelected ? 1 : 0}:${capabilities.map((c) => c.id).join(" ")}`;
60
+ }
61
+ //# sourceMappingURL=credential-capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-capabilities.js","sourceRoot":"","sources":["../../src/resolution/credential-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAiB,MAAM,yBAAyB,CAAC;AAGpE;;;;GAIG;AACH,MAAM,uBAAuB,GAAwB;IACnD,UAAU,CAAC,YAAY;IACvB,UAAU,CAAC,WAAW;CACvB,CAAC;AAEF,MAAM,UAAU,4BAA4B,CAC1C,IAAc,EACd,eAAuB;IAEvB,OAAO,eAAe,GAAG,CAAC,IAAI,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAc;IACxD,OAAO,IAAI,KAAK,UAAU,CAAC,WAAW,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAAgC;IAEhC,OAAO,CACL,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;QAC3C,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,6BAA6B,CAC3C,iBAAqC;IAErC,OAAO,CAAC,iBAAiB,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAA0B,EAC1B,cAAuB;IAEvB,OAAO,YAAY;SAChB,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,IAAI,UAAU,CAAC,SAAS,CAAC;SAC9D,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAA0B,EAC1B,WAAoB;IAEpB,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Identity Assertion Fragment Parsing
3
+ *
4
+ * Part of the consent-approve auth-gate fix
5
+ * (docs/superpowers/specs/2026-07-29-consent-approve-auth-gate-design.md §3.1).
6
+ * After credential/OAuth sign-in, the worker mints a grant-bound signed
7
+ * identity assertion and redirects the browser to the clickwrap consent
8
+ * screen carrying it in the URL **fragment**
9
+ * (`.../consent#identity_assertion=<token>`) rather than a query param.
10
+ * Fragments are never sent to the server — not in access logs, not in
11
+ * `Referer` — so this is the only way the assertion can be delivered without
12
+ * leaking it. That also means the server-rendered shell can never see it to
13
+ * pass it down as an attribute; the component must read `location.hash`
14
+ * itself once mounted in the browser.
15
+ *
16
+ * This module holds the pure parsing logic so it can be unit-tested in this
17
+ * package's node-environment vitest suite, which has no DOM and cannot mount
18
+ * the Lit component to exercise `location.hash` directly.
19
+ *
20
+ * @module @kya-os/consent/security/identity-assertion
21
+ */
22
+ /**
23
+ * Parse the `identity_assertion` value out of a URL fragment.
24
+ *
25
+ * Accepts a raw `location.hash`-shaped string, with or without its leading
26
+ * `#`. Returns `undefined` when the key is absent, the value is empty, or
27
+ * the fragment is empty/nullish. Never throws.
28
+ *
29
+ * @param hash - The fragment string, e.g. `location.hash`
30
+ * (`"#identity_assertion=abc"`)
31
+ * @returns The decoded assertion token, or `undefined` if not present
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * parseIdentityAssertionFromHash('#identity_assertion=abc123')
36
+ * // => 'abc123'
37
+ *
38
+ * parseIdentityAssertionFromHash('#a=1&identity_assertion=abc&b=2')
39
+ * // => 'abc'
40
+ *
41
+ * parseIdentityAssertionFromHash('#a=1&b=2')
42
+ * // => undefined
43
+ *
44
+ * parseIdentityAssertionFromHash('')
45
+ * // => undefined
46
+ * ```
47
+ */
48
+ export declare function parseIdentityAssertionFromHash(hash: string | undefined | null): string | undefined;
49
+ //# sourceMappingURL=identity-assertion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-assertion.d.ts","sourceRoot":"","sources":["../../src/security/identity-assertion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC9B,MAAM,GAAG,SAAS,CAgBpB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Identity Assertion Fragment Parsing
3
+ *
4
+ * Part of the consent-approve auth-gate fix
5
+ * (docs/superpowers/specs/2026-07-29-consent-approve-auth-gate-design.md §3.1).
6
+ * After credential/OAuth sign-in, the worker mints a grant-bound signed
7
+ * identity assertion and redirects the browser to the clickwrap consent
8
+ * screen carrying it in the URL **fragment**
9
+ * (`.../consent#identity_assertion=<token>`) rather than a query param.
10
+ * Fragments are never sent to the server — not in access logs, not in
11
+ * `Referer` — so this is the only way the assertion can be delivered without
12
+ * leaking it. That also means the server-rendered shell can never see it to
13
+ * pass it down as an attribute; the component must read `location.hash`
14
+ * itself once mounted in the browser.
15
+ *
16
+ * This module holds the pure parsing logic so it can be unit-tested in this
17
+ * package's node-environment vitest suite, which has no DOM and cannot mount
18
+ * the Lit component to exercise `location.hash` directly.
19
+ *
20
+ * @module @kya-os/consent/security/identity-assertion
21
+ */
22
+ /**
23
+ * Parse the `identity_assertion` value out of a URL fragment.
24
+ *
25
+ * Accepts a raw `location.hash`-shaped string, with or without its leading
26
+ * `#`. Returns `undefined` when the key is absent, the value is empty, or
27
+ * the fragment is empty/nullish. Never throws.
28
+ *
29
+ * @param hash - The fragment string, e.g. `location.hash`
30
+ * (`"#identity_assertion=abc"`)
31
+ * @returns The decoded assertion token, or `undefined` if not present
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * parseIdentityAssertionFromHash('#identity_assertion=abc123')
36
+ * // => 'abc123'
37
+ *
38
+ * parseIdentityAssertionFromHash('#a=1&identity_assertion=abc&b=2')
39
+ * // => 'abc'
40
+ *
41
+ * parseIdentityAssertionFromHash('#a=1&b=2')
42
+ * // => undefined
43
+ *
44
+ * parseIdentityAssertionFromHash('')
45
+ * // => undefined
46
+ * ```
47
+ */
48
+ export function parseIdentityAssertionFromHash(hash) {
49
+ if (!hash)
50
+ return undefined;
51
+ const withoutLeadingHash = hash.startsWith("#") ? hash.slice(1) : hash;
52
+ if (!withoutLeadingHash)
53
+ return undefined;
54
+ try {
55
+ const params = new URLSearchParams(withoutLeadingHash);
56
+ const value = params.get("identity_assertion");
57
+ return value ? value : undefined;
58
+ }
59
+ catch {
60
+ // URLSearchParams is very lenient and does not throw in practice, but
61
+ // guard anyway - a parsing failure here must never crash the consent
62
+ // screen, it should just mean "no assertion found".
63
+ return undefined;
64
+ }
65
+ }
66
+ //# sourceMappingURL=identity-assertion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-assertion.js","sourceRoot":"","sources":["../../src/security/identity-assertion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,8BAA8B,CAC5C,IAA+B;IAE/B,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5B,MAAM,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,IAAI,CAAC,kBAAkB;QAAE,OAAO,SAAS,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,kBAAkB,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;QACtE,qEAAqE;QACrE,oDAAoD;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -7,4 +7,5 @@
7
7
  */
8
8
  export * from "./escape.js";
9
9
  export * from "./validators.js";
10
+ export * from "./identity-assertion.js";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
@@ -7,4 +7,5 @@
7
7
  */
8
8
  export * from "./escape.js";
9
9
  export * from "./validators.js";
10
+ export * from "./identity-assertion.js";
10
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/consent",
3
- "version": "0.1.44",
3
+ "version": "0.1.47",
4
4
  "description": "Canonical consent page types, styles, and utilities for MCP-I and AgentShield",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",