@amalgm/channels 0.1.3 → 0.1.5-main.34175005481

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
@@ -20,8 +20,34 @@ that no computer has accepted yet. Chat sessions, transcripts, and agent
20
20
  execution stay on the pinned user's computer. The hosted service is its own
21
21
  deployable and does not run inside or depend on Amalgm Gateway.
22
22
 
23
+ Each hosted Channels environment reaches only its declared UI issuer and
24
+ database. Main and preview initially share the database by owner direction;
25
+ their public API and issuer identities remain distinct. Durable delivery leases
26
+ remain authoritative when multiple hosts share data.
27
+
23
28
  ## Axioms
24
29
 
30
+ Consumer assembly derives exact same-branch dependency pins from the declared
31
+ package manifests and registry candidate records. One pending composition per
32
+ branch preserves human edits; complete consumer checks for the exact merge tree govern its
33
+ merge, and publication never implies installed adoption.
34
+
35
+ Managed package delivery starts from a clean, exact main or preview source
36
+ commit. The workflow occurrence supplies only its generated version and source
37
+ record; tests run against those candidate inputs before packing. Every native
38
+ gate and publication use that same tarball and integrity. A candidate tag makes
39
+ bytes available to release assembly; it never promotes an installed runtime.
40
+ Release tooling remains available inside each owner repository so a developer
41
+ or CI job never needs access to another private product repository.
42
+ Registry credentials are available only to the final protected publication job,
43
+ after every native examination proves the exact candidate bytes.
44
+ The repository token creates only its own dependency proposals and explicitly
45
+ dispatches checks and delivery; every admitted gate proves the actual checkout,
46
+ including the exact two-parent merge commit that becomes managed source.
47
+
48
+ Managed releases bind to one exact published Core version and build from the
49
+ locked dependency graph on the supported Node toolchain.
50
+
25
51
  1. Every user delivery and every accepted inbound message belongs to exactly
26
52
  one authenticated user.
27
53
  2. A public send input never contains a user id, email address, phone number,
@@ -67,6 +93,9 @@ deployable and does not run inside or depend on Amalgm Gateway.
67
93
  a sent delivery to delivered or failed.
68
94
  19. The global CLI projects the same command definitions as MCP and reaches
69
95
  hosted effects only through Shell's authenticated loopback MCP route.
96
+ 20. The host validates its complete Core binding and every configured endpoint
97
+ before composing clients or workers; an isolated local host uses only
98
+ explicitly supplied loopback authorities.
70
99
 
71
100
  ## Tree
72
101
 
@@ -85,3 +114,10 @@ host/ Supabase, auth, provider, server, and Fly composition
85
114
  supabase/migrations/ durable schema and atomic RPCs
86
115
  skills/channels/ agent usage guidance
87
116
  ```
117
+
118
+ Hosted delivery examines the final immutable image under both declared managed
119
+ bindings before deploying that exact digest to its source branch's Fly app.
120
+ The host's own pipeline owns replacement, health and provider verification;
121
+ no hosted process updates its package tree in place. A local image examination
122
+ proves image behavior, while Fly networking and durable product journeys retain
123
+ their separate provider proof.
package/README.md CHANGED
@@ -73,3 +73,37 @@ purpose and invariants.
73
73
  ```bash
74
74
  npm run verify
75
75
  ```
76
+
77
+ ## Managed package delivery
78
+
79
+ Managed npm delivery uses `.github/workflows/publish-package.yml` after the
80
+ exact main/preview owner checks pass. The occurrence generates a unique
81
+ prerelease version and records its source SHA; it reruns the owner suite, packs
82
+ once, and installs that tarball on Linux, macOS and Windows before publication.
83
+ The `candidate-main`/`candidate-preview` tags are release-assembly inputs and
84
+ never select installed runtimes. `package.json` declares this owner's gates,
85
+ CLI probes, peer-only exports and lifecycle permissions. The standalone runner
86
+ under `scripts/release/` is intentionally copied across owners to preserve
87
+ private repository access boundaries. The final publish step uses the `NPM_TOKEN`
88
+ secret in the `npm-release` environment. Where npm trusted publishing is
89
+ configured for this repository's `publish-package.yml` and that environment,
90
+ the token can be omitted. Authentication does not replace native certification,
91
+ exact source records or artifact integrity; private source repositories do not
92
+ receive npm's public-source provenance.
93
+
94
+ Hosted delivery is separately wired in `release-hosted.yml`: it builds the exact
95
+ source image, tests both declared bindings without network access, deploys the
96
+ same digest to the selected Fly app, then verifies machine identity and public
97
+ readiness. `package.json` owns the host declaration. The Python effect runner is
98
+ an intentional standalone copy from UI; no other private repository is required.
99
+ Live provider and durable product-flow proof remain separate release obligations.
100
+
101
+ Managed dependency reconciliation reads this owner’s declared manifests and
102
+ updates exact same-branch registry candidates in one pending composition PR per
103
+ branch. The repository token explicitly dispatches the owner checks. Every declared gate must
104
+ pass for the exact merge tree; an atomic expected-base update prevents merging
105
+ with untested concurrent source. Human additions or amendments are preserved.
106
+ The half-hour CI reconciliation recovers missed dispatch hints. Assembly runs
107
+ no dependency code or lifecycle hooks, and repeated owner checks do not publish
108
+ another candidate for unchanged source. Repository policy must allow GitHub Actions to create pull requests; no
109
+ cross-repository credential or paid auto-merge feature is required.
@@ -1,10 +1,14 @@
1
+ import { isLoopbackEndpoint, resolveRuntimeEndpoint, validateRuntimeEndpointEnvironment } from '@amalgm/core/binding';
1
2
  export function channelsHostConfig(env = process.env) {
3
+ const publicOrigin = required(env.AMALGAM_PUBLIC_ORIGIN, 'AMALGAM_PUBLIC_ORIGIN');
4
+ const isolatedOrigin = isLoopbackEndpoint(publicOrigin) ? publicOrigin : undefined;
5
+ const binding = validateRuntimeEndpointEnvironment(env, isolatedOrigin);
2
6
  return Object.freeze({
3
7
  port: integer(env.PORT, 8080, 1, 65_535),
4
- publicOrigin: httpsUrl(env.AMALGAM_PUBLIC_ORIGIN, 'AMALGAM_PUBLIC_ORIGIN'),
5
- supabaseUrl: httpsUrl(env.SUPABASE_URL ?? env.NEXT_PUBLIC_SUPABASE_URL, 'SUPABASE_URL'),
8
+ publicOrigin: resolveRuntimeEndpoint(binding, 'channels', publicOrigin, isolatedOrigin),
9
+ supabaseUrl: resolveRuntimeEndpoint(binding, 'supabase', required(env.SUPABASE_URL ?? env.NEXT_PUBLIC_SUPABASE_URL, 'SUPABASE_URL'), isolatedOrigin),
6
10
  supabaseServiceRoleKey: required(env.SUPABASE_SERVICE_ROLE_KEY, 'SUPABASE_SERVICE_ROLE_KEY'),
7
- authorizationIssuer: httpsUrl(env.AMALGM_AUTHORIZATION_ISSUER, 'AMALGM_AUTHORIZATION_ISSUER'),
11
+ authorizationIssuer: resolveRuntimeEndpoint(binding, 'app', required(env.AMALGM_AUTHORIZATION_ISSUER, 'AMALGM_AUTHORIZATION_ISSUER'), isolatedOrigin),
8
12
  resendApiKey: required(env.RESEND_API_KEY, 'RESEND_API_KEY'),
9
13
  resendWebhookSecret: required(env.RESEND_WEBHOOK_SECRET, 'RESEND_WEBHOOK_SECRET'),
10
14
  emailFrom: required(env.CHANNELS_EMAIL_FROM, 'CHANNELS_EMAIL_FROM'),
@@ -17,14 +21,6 @@ function required(value, name) {
17
21
  throw new Error(`${name} is required`);
18
22
  return value.trim();
19
23
  }
20
- function httpsUrl(value, name) {
21
- const parsed = new URL(required(value, name));
22
- const local = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';
23
- if (parsed.protocol !== 'https:' && !(local && parsed.protocol === 'http:')) {
24
- throw new Error(`${name} must use HTTPS`);
25
- }
26
- return parsed.toString().replace(/\/$/, '');
27
- }
28
24
  function integer(value, fallback, minimum, maximum) {
29
25
  const parsed = value === undefined ? fallback : Number(value);
30
26
  if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../host/config.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,kBAAkB,CAChC,MAAoD,OAAO,CAAC,GAAG;IAE/D,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;QACxC,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;QAC1E,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,wBAAwB,EAAE,cAAc,CAAC;QACvF,sBAAsB,EAAE,QAAQ,CAAC,GAAG,CAAC,yBAAyB,EAAE,2BAA2B,CAAC;QAC5F,mBAAmB,EAAE,QAAQ,CAAC,GAAG,CAAC,2BAA2B,EAAE,6BAA6B,CAAC;QAC7F,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,gBAAgB,CAAC;QAC5D,mBAAmB,EAAE,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;QACjF,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,qBAAqB,CAAC;QACnE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,oBAAoB,EAAE,sBAAsB,CAAC;QACtE,iBAAiB,EAAE,QAAQ,CAAC,GAAG,CAAC,4BAA4B,EAAE,8BAA8B,CAAC;KAC9F,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,IAAY;IACvD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,IAAY;IACvD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,CAAC;IACjF,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,OAAO,CACd,KAAyB,EACzB,QAAgB,EAChB,OAAe,EACf,OAAe;IAEf,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,OAAO,IAAI,MAAM,GAAG,OAAO,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,OAAO,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../host/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC;AAetH,MAAM,UAAU,kBAAkB,CAChC,MAAoD,OAAO,CAAC,GAAG;IAE/D,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC;IAClF,MAAM,cAAc,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IACnF,MAAM,OAAO,GAAG,kCAAkC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;QACxC,YAAY,EAAE,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,CAAC;QACvF,WAAW,EAAE,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,wBAAwB,EAAE,cAAc,CAAC,EAAE,cAAc,CAAC;QACpJ,sBAAsB,EAAE,QAAQ,CAAC,GAAG,CAAC,yBAAyB,EAAE,2BAA2B,CAAC;QAC5F,mBAAmB,EAAE,sBAAsB,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,2BAA2B,EAAE,6BAA6B,CAAC,EAAE,cAAc,CAAC;QACrJ,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,gBAAgB,CAAC;QAC5D,mBAAmB,EAAE,QAAQ,CAAC,GAAG,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;QACjF,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,qBAAqB,CAAC;QACnE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,oBAAoB,EAAE,sBAAsB,CAAC;QACtE,iBAAiB,EAAE,QAAQ,CAAC,GAAG,CAAC,4BAA4B,EAAE,8BAA8B,CAAC;KAC9F,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,IAAY;IACvD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,OAAO,CACd,KAAyB,EACzB,QAAgB,EAChB,OAAe,EACf,OAAe;IAEf,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,OAAO,IAAI,MAAM,GAAG,OAAO,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,OAAO,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/channels",
3
- "version": "0.1.3",
3
+ "version": "0.1.5-main.34175005481",
4
4
  "description": "Amalgm's SDK and hosted service for durable bidirectional user channels.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -46,13 +46,19 @@
46
46
  "test": "tsx --test test/*.test.ts",
47
47
  "verify": "npm run check && npm test && npm run build && tsx scripts/check-cli-artifact.ts",
48
48
  "prepack": "npm run build",
49
- "start": "node dist/host/main.js"
49
+ "start": "node dist/host/main.js",
50
+ "release:admit": "node scripts/release/package.mjs admit",
51
+ "release:prepare": "node scripts/release/package.mjs prepare",
52
+ "release:examine": "node scripts/release/package.mjs examine",
53
+ "release:publish": "node scripts/release/package.mjs publish",
54
+ "release:compose": "node scripts/release/compose.mjs",
55
+ "test:release": "node --test scripts/release/*.test.mjs"
50
56
  },
51
57
  "engines": {
52
- "node": ">=20"
58
+ "node": ">=24"
53
59
  },
54
60
  "dependencies": {
55
- "@amalgm/core": "0.4.6",
61
+ "@amalgm/core": "0.4.7",
56
62
  "@modelcontextprotocol/sdk": "^1.30.0",
57
63
  "@supabase/supabase-js": "2.57.4",
58
64
  "jose": "^6.1.0",
@@ -62,5 +68,40 @@
62
68
  "@types/node": "^26.1.2",
63
69
  "tsx": "^4.23.1",
64
70
  "typescript": "5.9.3"
71
+ },
72
+ "amalgmRelease": {
73
+ "schema": 1,
74
+ "workflow": "verify.yml",
75
+ "jobs": [
76
+ "verify"
77
+ ],
78
+ "verify": "verify",
79
+ "cli": [
80
+ "amalgm-channels"
81
+ ]
82
+ },
83
+ "allowScripts": {
84
+ "esbuild@0.28.2": true,
85
+ "fsevents@2.3.3": false
86
+ },
87
+ "amalgmHosts": {
88
+ "channels": {
89
+ "directory": ".",
90
+ "context": ".",
91
+ "dockerfile": "Dockerfile"
92
+ }
93
+ },
94
+ "amalgmComposition": {
95
+ "schema": 1,
96
+ "manifests": [
97
+ "package.json"
98
+ ]
99
+ },
100
+ "gitHead": "789d2d7025a41b9d3911faff030e088fb01650d9",
101
+ "amalgmSource": {
102
+ "repository": "amalgm-inc/amalgm-channels",
103
+ "branch": "main",
104
+ "commit": "789d2d7025a41b9d3911faff030e088fb01650d9",
105
+ "occurrence": "34175005481"
65
106
  }
66
107
  }