@amalgm/core 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PURPOSE.md CHANGED
@@ -100,6 +100,8 @@ that composes an exact Core release with the other product releases.
100
100
  17. **Retirement is explicit subtraction.** Every retired Engine prefix stays
101
101
  named as evidence but is absent from the active route table, so dead
102
102
  compatibility surfaces cannot masquerade as unfinished product work.
103
+ The retired `/email` compatibility door is owned by neither Core nor
104
+ Shell; current-user delivery belongs to the standalone Channels product.
103
105
  18. **Machine setup is one trust rail with two entrances.** Browser polling and
104
106
  an approved setup code converge before the same registration, credential
105
107
  split, installation, canonical-runtime, and readiness path;
@@ -125,6 +127,8 @@ that composes an exact Core release with the other product releases.
125
127
  credential may mint an audience- and scope-exact access token, but every
126
128
  resource request also proves possession of that machine's key; Core owns
127
129
  the claims and renewal law while hosts own keys, storage, signing, and HTTP.
130
+ Behind a proxy, the configured public origin is authority for the DPoP URL;
131
+ caller-controlled forwarding headers are not.
128
132
  23. **Machine key replacement is an explicit recovery, never startup repair.**
129
133
  Ordinary registration may pin an absent key or reuse the same key; replacing
130
134
  it requires fresh user approval, proof of the candidate private key, and a
@@ -17,4 +17,10 @@ export interface DpopSignerPort {
17
17
  /** RFC 9449 htu excludes query and fragment and uses an absolute URI. */
18
18
  export declare function normalizeDpopHtu(value: string): string;
19
19
  export declare function normalizeDpopMethod(value: string): string;
20
+ /**
21
+ * Reconstruct the public resource URL behind a reverse proxy without trusting
22
+ * caller-controlled forwarding headers. Deployment config owns the origin;
23
+ * the HTTP request contributes only its origin-form path and query.
24
+ */
25
+ export declare function publicResourceRequestUrl(publicOrigin: string, requestTarget: string): string;
20
26
  //# sourceMappingURL=dpop.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../../../src/identity/authorization/dpop.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD"}
1
+ {"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../../../src/identity/authorization/dpop.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAe5F"}
@@ -16,4 +16,24 @@ export function normalizeDpopMethod(value) {
16
16
  throw new TypeError('DPoP method is invalid');
17
17
  return method;
18
18
  }
19
+ /**
20
+ * Reconstruct the public resource URL behind a reverse proxy without trusting
21
+ * caller-controlled forwarding headers. Deployment config owns the origin;
22
+ * the HTTP request contributes only its origin-form path and query.
23
+ */
24
+ export function publicResourceRequestUrl(publicOrigin, requestTarget) {
25
+ const origin = new URL(publicOrigin);
26
+ const loopback = origin.hostname === 'localhost' || origin.hostname === '127.0.0.1';
27
+ if ((origin.protocol !== 'https:' && !(loopback && origin.protocol === 'http:'))
28
+ || origin.username
29
+ || origin.password
30
+ || origin.pathname !== '/'
31
+ || origin.search
32
+ || origin.hash)
33
+ throw new TypeError('Public resource origin must be an HTTPS origin');
34
+ if (!requestTarget.startsWith('/') || requestTarget.startsWith('//')) {
35
+ throw new TypeError('Resource request target must use origin form');
36
+ }
37
+ return new URL(requestTarget, origin).toString();
38
+ }
19
39
  //# sourceMappingURL=dpop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dpop.js","sourceRoot":"","sources":["../../../src/identity/authorization/dpop.ts"],"names":[],"mappings":"AAmBA,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;IAClB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;IAClB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"dpop.js","sourceRoot":"","sources":["../../../src/identity/authorization/dpop.ts"],"names":[],"mappings":"AAmBA,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;IAClB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;IAClB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,YAAoB,EAAE,aAAqB;IAClF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,CAAC;IACpF,IACE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;WACzE,MAAM,CAAC,QAAQ;WACf,MAAM,CAAC,QAAQ;WACf,MAAM,CAAC,QAAQ,KAAK,GAAG;WACvB,MAAM,CAAC,MAAM;WACb,MAAM,CAAC,IAAI;QACd,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;AACnD,CAAC"}
@@ -9,7 +9,7 @@
9
9
  * under its own '/pty' handling).
10
10
  *
11
11
  * Counts, pinned by tests: 3 gateway prefixes, 5 gateway exact paths,
12
- * 3 port-monitor prefixes, 1 chat prefix, 22 active MCP prefixes.
12
+ * 3 port-monitor prefixes, 1 chat prefix, 21 active MCP prefixes.
13
13
  *
14
14
  * This is product configuration riding in the kernel repo for the
15
15
  * cutover: the table SHAPE is core's; these CONTENTS belong to the
@@ -23,8 +23,10 @@ import type { RouteTable } from './routing.js';
23
23
  * `/tasks` is the superseded SQLite scheduler facade; `/mcp-connections` is
24
24
  * the superseded second registry now represented by Tools connection records
25
25
  * plus credential references resolved by Core's machine-local vault; `/github`
26
- * is superseded by the next cloud integration and credential collection model.
26
+ * is superseded by the next cloud integration and credential collection model;
27
+ * `/email` was the in-process Notifications compatibility door and is replaced
28
+ * by the independently deployed Channels product.
27
29
  */
28
- export declare const retiredEngineRoutePrefixes: readonly ["/tasks", "/mcp-connections", "/github"];
30
+ export declare const retiredEngineRoutePrefixes: readonly ["/tasks", "/mcp-connections", "/github", "/email"];
29
31
  export declare const shippedRouteTable: RouteTable;
30
32
  //# sourceMappingURL=shipped-routes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shipped-routes.d.ts","sourceRoot":"","sources":["../../src/transport/shipped-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,oDAAqD,CAAC;AAE7F,eAAO,MAAM,iBAAiB,EAAE,UA6B/B,CAAC"}
1
+ {"version":3,"file":"shipped-routes.d.ts","sourceRoot":"","sources":["../../src/transport/shipped-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,8DAA+D,CAAC;AAEvG,eAAO,MAAM,iBAAiB,EAAE,UA4B/B,CAAC"}
@@ -9,7 +9,7 @@
9
9
  * under its own '/pty' handling).
10
10
  *
11
11
  * Counts, pinned by tests: 3 gateway prefixes, 5 gateway exact paths,
12
- * 3 port-monitor prefixes, 1 chat prefix, 22 active MCP prefixes.
12
+ * 3 port-monitor prefixes, 1 chat prefix, 21 active MCP prefixes.
13
13
  *
14
14
  * This is product configuration riding in the kernel repo for the
15
15
  * cutover: the table SHAPE is core's; these CONTENTS belong to the
@@ -22,9 +22,11 @@
22
22
  * `/tasks` is the superseded SQLite scheduler facade; `/mcp-connections` is
23
23
  * the superseded second registry now represented by Tools connection records
24
24
  * plus credential references resolved by Core's machine-local vault; `/github`
25
- * is superseded by the next cloud integration and credential collection model.
25
+ * is superseded by the next cloud integration and credential collection model;
26
+ * `/email` was the in-process Notifications compatibility door and is replaced
27
+ * by the independently deployed Channels product.
26
28
  */
27
- export const retiredEngineRoutePrefixes = ['/tasks', '/mcp-connections', '/github'];
29
+ export const retiredEngineRoutePrefixes = ['/tasks', '/mcp-connections', '/github', '/email'];
28
30
  export const shippedRouteTable = {
29
31
  gatewayPrefixes: ['/__amalgm', '/diagnostics', '/pty'],
30
32
  gatewayExactPaths: ['/', '/healthz', '/runtime-state', '/pty/session', '/pty/resize'],
@@ -42,7 +44,6 @@ export const shippedRouteTable = {
42
44
  '/state',
43
45
  '/local',
44
46
  '/credentials',
45
- '/email',
46
47
  '/slack',
47
48
  '/user-api-keys',
48
49
  '/apps',
@@ -1 +1 @@
1
- {"version":3,"file":"shipped-routes.js","sourceRoot":"","sources":["../../src/transport/shipped-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAU,CAAC;AAE7F,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,eAAe,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC;IACtD,iBAAiB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,CAAC;IACrF,mBAAmB,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,eAAe,CAAC;IAC9D,YAAY,EAAE,CAAC,OAAO,CAAC;IACvB,WAAW,EAAE;QACX,MAAM;QACN,SAAS;QACT,cAAc;QACd,iBAAiB;QACjB,YAAY;QACZ,kBAAkB;QAClB,KAAK;QACL,UAAU;QACV,QAAQ;QACR,QAAQ;QACR,cAAc;QACd,QAAQ;QACR,QAAQ;QACR,gBAAgB;QAChB,OAAO;QACP,YAAY;QACZ,SAAS;QACT,eAAe;QACf,gBAAgB;QAChB,SAAS;QACT,mBAAmB;QACnB,UAAU;KACX;CACF,CAAC"}
1
+ {"version":3,"file":"shipped-routes.js","sourceRoot":"","sources":["../../src/transport/shipped-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;AAEvG,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,eAAe,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC;IACtD,iBAAiB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,CAAC;IACrF,mBAAmB,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,eAAe,CAAC;IAC9D,YAAY,EAAE,CAAC,OAAO,CAAC;IACvB,WAAW,EAAE;QACX,MAAM;QACN,SAAS;QACT,cAAc;QACd,iBAAiB;QACjB,YAAY;QACZ,kBAAkB;QAClB,KAAK;QACL,UAAU;QACV,QAAQ;QACR,QAAQ;QACR,cAAc;QACd,QAAQ;QACR,gBAAgB;QAChB,OAAO;QACP,YAAY;QACZ,SAAS;QACT,eAAe;QACf,gBAAgB;QAChB,SAAS;QACT,mBAAmB;QACnB,UAAU;KACX;CACF,CAAC"}
@@ -16,14 +16,16 @@ needs.
16
16
  set, expiry, token id, signing key, and device-key thumbprint.
17
17
  3. Every resource request has a fresh DPoP proof bound to its method, URL,
18
18
  access token, and machine key.
19
- 4. The broker caches an exact grant, refreshes before expiry with jitter,
19
+ 4. A proxied resource reconstructs that URL from its configured public origin
20
+ and the origin-form request target; forwarding headers are not authority.
21
+ 5. The broker caches an exact grant, refreshes before expiry with jitter,
20
22
  single-flights concurrent renewal, and performs no silent auth fallback.
21
- 5. Audiences and scopes are closed sets. Adding a consumer changes this module
23
+ 6. Audiences and scopes are closed sets. Adding a consumer changes this module
22
24
  and its tests before any issuer or verifier accepts it.
23
- 6. A machine key is pinned once. Replacement requires an explicit, browser-
25
+ 7. A machine key is pinned once. Replacement requires an explicit, browser-
24
26
  approved recovery bound to the expected old thumbprint and a different
25
27
  candidate key; retrying an already completed replacement is idempotent.
26
- 7. Provider access is memory-only. Registration and machine resume never
28
+ 8. Provider access is memory-only. Registration and machine resume never
27
29
  persist an access token, DPoP proof, or provider proxy credential; resume
28
30
  removes retired proxy and HMAC fields left by older installations.
29
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/core",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "The Amalgm kernel SDK — identity, transport, supervision, and host capability contracts behind host-injected adapters.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",