@amalgm/automations 0.4.1 → 0.4.2

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/AXIOMS.md CHANGED
@@ -64,6 +64,9 @@
64
64
  aliases for one another.
65
65
  23. Automations is a standalone hosted service. Gateway owns none of its API,
66
66
  scheduling, claim, execution, or persistence path.
67
+ Its host validates Core's complete environment binding before opening its
68
+ database, issuer, public API or webhook authority; local has no managed
69
+ service fallback.
67
70
  24. The durable run ledger is the offline queue. The platform never keeps a
68
71
  second online-machine delivery buffer and never drops an unclaimed run.
69
72
  25. A run advances through its immutable plan in order. Every step transition
package/PURPOSE.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
+ Managed releases bind to one exact published Core version and build from the
6
+ locked dependency graph on the supported Node toolchain.
7
+
5
8
  Automations is the sole owner of Amalgm automation behavior and data. It lets an
6
9
  authenticated user create, inspect, change, delete, and manually run automation
7
10
  configuration — an automation belongs to one user and one target, may own any
@@ -10,6 +13,11 @@ have each trigger occurrence run on the selected existing Amalgm machine.
10
13
  Supabase holds everything except execution: the automation, its triggers, the
11
14
  complete workflow, and permanent run history.
12
15
 
16
+ Each hosted environment reaches only its declared UI issuer, database and
17
+ webhook authority. Main and preview initially share the database by owner
18
+ direction; their public API and issuer identities remain distinct. Durable
19
+ claims remain the single authority for work even when hosts share data.
20
+
13
21
  The product has two composable halves over that one state:
14
22
 
15
23
  - **The configuration control plane** — one ergonomic, auth-bound SDK contract
@@ -1,12 +1,16 @@
1
+ import { isLoopbackEndpoint, resolveRuntimeEndpoint, validateRuntimeEndpointEnvironment } from '@amalgm/core/binding';
1
2
  export function automationsHostConfig(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: url(env.AMALGAM_PUBLIC_ORIGIN, 'AMALGAM_PUBLIC_ORIGIN'),
5
- webhookOrigin: url(env.AUTOMATIONS_WEBHOOK_ORIGIN, 'AUTOMATIONS_WEBHOOK_ORIGIN'),
8
+ publicOrigin: resolveRuntimeEndpoint(binding, 'automations', publicOrigin, isolatedOrigin),
9
+ webhookOrigin: resolveRuntimeEndpoint(binding, 'automations', required(env.AUTOMATIONS_WEBHOOK_ORIGIN, 'AUTOMATIONS_WEBHOOK_ORIGIN'), isolatedOrigin),
6
10
  webhookTokenKey: secret(env.AUTOMATIONS_WEBHOOK_TOKEN_KEY, 'AUTOMATIONS_WEBHOOK_TOKEN_KEY'),
7
- supabaseUrl: url(env.SUPABASE_URL ?? env.NEXT_PUBLIC_SUPABASE_URL, 'SUPABASE_URL'),
11
+ supabaseUrl: resolveRuntimeEndpoint(binding, 'supabase', required(env.SUPABASE_URL ?? env.NEXT_PUBLIC_SUPABASE_URL, 'SUPABASE_URL'), isolatedOrigin),
8
12
  supabaseServiceRoleKey: required(env.SUPABASE_SERVICE_ROLE_KEY, 'SUPABASE_SERVICE_ROLE_KEY'),
9
- authorizationIssuer: url(env.AMALGM_AUTHORIZATION_ISSUER, 'AMALGM_AUTHORIZATION_ISSUER'),
13
+ authorizationIssuer: resolveRuntimeEndpoint(binding, 'app', required(env.AMALGM_AUTHORIZATION_ISSUER, 'AMALGM_AUTHORIZATION_ISSUER'), isolatedOrigin),
10
14
  schedulerIntervalMs: integer(env.AUTOMATIONS_SCHEDULER_INTERVAL_MS, 1_000, 250, 60_000),
11
15
  });
12
16
  }
@@ -21,14 +25,6 @@ function secret(value, name) {
21
25
  throw new Error(`${name} must contain at least 32 bytes`);
22
26
  return result;
23
27
  }
24
- function url(value, name) {
25
- const parsed = new URL(required(value, name));
26
- const local = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';
27
- if (parsed.protocol !== 'https:' && !(local && parsed.protocol === 'http:')) {
28
- throw new Error(`${name} must use HTTPS`);
29
- }
30
- return parsed.toString().replace(/\/$/, '');
31
- }
32
28
  function integer(value, fallback, minimum, maximum) {
33
29
  const parsed = value === undefined ? fallback : Number(value);
34
30
  if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) {
@@ -1 +1 @@
1
- {"$schema":"https://schemas.agentskills.io/discovery/0.2.0/schema.json","skills":[{"name":"amalgm-automations","description":"Set up, operate, and troubleshoot Amalgm Automations through MCP or the amalgm automations CLI. Use for installation, Google sign-in, scheduled or webhook workflows, Run Now, run history, and Automations support.","type":"archive","url":"./amalgm-automations.5e4e14f0ace632c8383cd014e1f0f34b24ec0d5c5600132a840abc4c313b31d4.tgz","digest":"sha256:5e4e14f0ace632c8383cd014e1f0f34b24ec0d5c5600132a840abc4c313b31d4"}]}
1
+ {"$schema":"https://schemas.agentskills.io/discovery/0.2.0/schema.json","skills":[{"name":"amalgm-automations","description":"Set up, operate, and troubleshoot Amalgm Automations through MCP or the amalgm automations CLI. Use for installation, Google sign-in, scheduled or webhook workflows, Run Now, run history, and Automations support.","type":"archive","url":"./amalgm-automations.f64db3414c22f330c2c83a5d1dc76949d7a95f3c9ba06a94c5fbd9c4024d4acd.tgz","digest":"sha256:f64db3414c22f330c2c83a5d1dc76949d7a95f3c9ba06a94c5fbd9c4024d4acd"}]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/automations",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Amalgm's automation SDK: durable trigger admission and target-machine execution.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -45,7 +45,7 @@
45
45
  "README.md"
46
46
  ],
47
47
  "scripts": {
48
- "build": "rm -rf dist && tsc -p tsconfig.build.json && tsx scripts/mark-executables.ts && tsx scripts/build-public-skill.ts",
48
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && tsx scripts/mark-executables.ts && tsx scripts/build-public-skill.ts",
49
49
  "check": "tsx scripts/check-tree.ts && tsc -p tsconfig.json --noEmit",
50
50
  "test": "tsx --test test/*.test.ts",
51
51
  "test:supabase": "tsx --test test/integration/postgres.test.ts",
@@ -56,10 +56,10 @@
56
56
  "start": "node dist/host/main.js"
57
57
  },
58
58
  "engines": {
59
- "node": ">=20"
59
+ "node": ">=24"
60
60
  },
61
61
  "dependencies": {
62
- "@amalgm/core": "0.4.4",
62
+ "@amalgm/core": "0.4.7",
63
63
  "@modelcontextprotocol/sdk": "^1.30.0",
64
64
  "@supabase/supabase-js": "2.57.4",
65
65
  "cron-parser": "^5.4.0",