@cat-factory/server 0.159.0 → 0.161.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.
- package/dist/agents/ContainerAgentExecutor.d.ts.map +1 -1
- package/dist/agents/ContainerAgentExecutor.js +5 -2
- package/dist/agents/ContainerAgentExecutor.js.map +1 -1
- package/dist/agents/jobBody.d.ts.map +1 -1
- package/dist/agents/jobBody.js +6 -3
- package/dist/agents/jobBody.js.map +1 -1
- package/dist/events/machineSubscribe.d.ts +56 -0
- package/dist/events/machineSubscribe.d.ts.map +1 -0
- package/dist/events/machineSubscribe.js +75 -0
- package/dist/events/machineSubscribe.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/events/EventsRelayController.d.ts +3 -1
- package/dist/modules/events/EventsRelayController.d.ts.map +1 -1
- package/dist/modules/events/EventsRelayController.js +50 -1
- package/dist/modules/events/EventsRelayController.js.map +1 -1
- package/dist/persistence/rpc-allowlist.d.ts +37 -0
- package/dist/persistence/rpc-allowlist.d.ts.map +1 -0
- package/dist/persistence/rpc-allowlist.js +901 -0
- package/dist/persistence/rpc-allowlist.js.map +1 -0
- package/dist/persistence/rpc.d.ts +6 -34
- package/dist/persistence/rpc.d.ts.map +1 -1
- package/dist/persistence/rpc.js +6 -864
- package/dist/persistence/rpc.js.map +1 -1
- package/package.json +8 -8
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { TOKEN_AUDIENCE, signerFor } from '../../auth/signing.js';
|
|
3
|
+
import { authorizeMachineSubscribe } from '../../events/machineSubscribe.js';
|
|
4
|
+
import { param } from '../../http/params.js';
|
|
3
5
|
/**
|
|
4
6
|
* Upper bound on a relayed `payload` frame (characters). A serialized `WorkspaceEvent` is small
|
|
5
7
|
* (ids + a reason + a compact instance snapshot); 1 MiB is a generous ceiling that still brakes a
|
|
@@ -8,7 +10,9 @@ import { TOKEN_AUDIENCE, signerFor } from '../../auth/signing.js';
|
|
|
8
10
|
*/
|
|
9
11
|
const MAX_RELAYED_PAYLOAD_CHARS = 1_000_000;
|
|
10
12
|
/**
|
|
11
|
-
* The mothership-mode real-time
|
|
13
|
+
* The mothership-mode real-time machine API — BOTH directions:
|
|
14
|
+
* `POST /internal/events/publish` (upstream) and
|
|
15
|
+
* `GET /internal/events/subscribe/:workspaceId` (inbound).
|
|
12
16
|
*
|
|
13
17
|
* A mothership-mode local node runs the engine locally but delegates org/durable state to the
|
|
14
18
|
* mothership. Its engine events must ALSO reach the mothership's real-time fan-out, so a hosted
|
|
@@ -91,6 +95,51 @@ export function eventsRelayController() {
|
|
|
91
95
|
}
|
|
92
96
|
return c.json({ ok: true });
|
|
93
97
|
});
|
|
98
|
+
// The INBOUND leg: the node subscribes to a workspace's stream so org activity raised on the
|
|
99
|
+
// mothership (a hosted teammate, or a peer laptop relaying upstream) reaches the laptop's SPA.
|
|
100
|
+
//
|
|
101
|
+
// It is deliberately NOT a new fan-out. The upgrade is handed to the SAME per-workspace realtime
|
|
102
|
+
// transport the browser stream uses (`gateways.realtime.upgrade` — the `WorkspaceEventsHub`
|
|
103
|
+
// Durable Object on Cloudflare), so a subscribed node is just another socket in the workspace's
|
|
104
|
+
// room and every event reaches laptops and browsers through one code path. The node's stable
|
|
105
|
+
// `?cid=` rides through to that transport, which is what lets the mothership skip echoing the
|
|
106
|
+
// node's OWN relayed events back to it (the outbound leg stamps the same id as
|
|
107
|
+
// `originConnectionId`).
|
|
108
|
+
//
|
|
109
|
+
// Auth is the shared `authorizeMachineSubscribe` (token pin → capability → account scope), the
|
|
110
|
+
// same helper the Node facade calls from its HTTP-server `upgrade` listener — Node can't upgrade
|
|
111
|
+
// from a Hono `Response`, so this handler is unreachable there, exactly like the browser stream's
|
|
112
|
+
// GET in `eventsController`.
|
|
113
|
+
app.get(`/internal/events/subscribe/:workspaceId`, async (c) => {
|
|
114
|
+
const container = c.get('container');
|
|
115
|
+
const workspaceId = param(c, 'workspaceId');
|
|
116
|
+
// The scope resolution reuses the mothership's own repository registry (attached alongside the
|
|
117
|
+
// relay on every mothership), exactly like the publish handler above. The registry is
|
|
118
|
+
// reflective (`Record<string, Record<string, fn>>`), so narrow the one method we call.
|
|
119
|
+
const workspaceRepository = container.repositories?.workspaceRepository;
|
|
120
|
+
const auth = await authorizeMachineSubscribe({
|
|
121
|
+
auth: container.config.auth,
|
|
122
|
+
token: c.req.header('authorization'),
|
|
123
|
+
workspaceId,
|
|
124
|
+
accountOf: workspaceRepository?.accountOf
|
|
125
|
+
? (id) => workspaceRepository.accountOf(id)
|
|
126
|
+
: undefined,
|
|
127
|
+
});
|
|
128
|
+
if (!auth.ok) {
|
|
129
|
+
return c.json({
|
|
130
|
+
ok: false,
|
|
131
|
+
error: { code: auth.status === 404 ? 'not_found' : 'forbidden', message: auth.message },
|
|
132
|
+
}, auth.status);
|
|
133
|
+
}
|
|
134
|
+
// Checked AFTER auth so the handshake shape isn't probeable without a token.
|
|
135
|
+
if (c.req.header('Upgrade')?.toLowerCase() !== 'websocket') {
|
|
136
|
+
return c.text('expected a websocket upgrade', 426);
|
|
137
|
+
}
|
|
138
|
+
const upgraded = await container.gateways.realtime.upgrade(workspaceId, c.req.raw);
|
|
139
|
+
if (!upgraded)
|
|
140
|
+
return c.text('real-time events are not enabled', 501);
|
|
141
|
+
return upgraded;
|
|
142
|
+
});
|
|
94
143
|
return app;
|
|
95
144
|
}
|
|
96
145
|
//# sourceMappingURL=EventsRelayController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventsRelayController.js","sourceRoot":"","sources":["../../../src/modules/events/EventsRelayController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAuB,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"EventsRelayController.js","sourceRoot":"","sources":["../../../src/modules/events/EventsRelayController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAuB,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtF,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,yBAAyB,GAAG,SAAS,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/C,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAEpC,0FAA0F;QAC1F,yBAAyB;QACzB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAA;QAClD,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;QACvE,MAAM,OAAO,GAAG,MAAM;YACpB,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,CAAiB,KAAK,EAAE,EAAE,GAAG,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC;YACxF,CAAC,CAAC,IAAI,CAAA;QACR,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE,EAC7E,GAAG,CACJ,CAAA;QACH,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,iBAAiB,CAAA;QACzC,yFAAyF;QACzF,4FAA4F;QAC5F,MAAM,mBAAmB,GAAG,SAAS,CAAC,YAAY,EAAE,mBAAmB,CAAA;QACvE,IAAI,CAAC,KAAK,IAAI,CAAC,mBAAmB,EAAE,SAAS,EAAE,CAAC;YAC9C,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,EAC9E,GAAG,CACJ,CAAA;QACH,CAAC;QAED,IAAI,IAA0B,CAAA;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAA;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAC7E,GAAG,CACJ,CAAA;QACH,CAAC;QACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACtF,OAAO,CAAC,CAAC,IAAI,CACX;gBACE,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,sCAAsC,EAAE;aAC/E,EACD,GAAG,CACJ,CAAA;QACH,CAAC;QACD,iGAAiG;QACjG,wFAAwF;QACxF,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,yBAAyB,EAAE,CAAC;YACpD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;QAChG,CAAC;QAED,iGAAiG;QACjG,kGAAkG;QAClG,+FAA+F;QAC/F,mBAAmB;QACnB,MAAM,SAAS,GAAG,CAAC,MACjB,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAC/C,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAA8B,CAAA;QACtD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAChE,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE,EAC3E,GAAG,CACJ,CAAA;QACH,CAAC;QAED,+FAA+F;QAC/F,gGAAgG;QAChG,kGAAkG;QAClG,6EAA6E;QAC7E,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,MAAM,CAAC;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,kBAAkB,EAChB,OAAO,IAAI,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI;aAC/E,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7B,CAAC,CAAC,CAAA;IAEF,6FAA6F;IAC7F,+FAA+F;IAC/F,EAAE;IACF,iGAAiG;IACjG,4FAA4F;IAC5F,gGAAgG;IAChG,6FAA6F;IAC7F,8FAA8F;IAC9F,+EAA+E;IAC/E,yBAAyB;IACzB,EAAE;IACF,+FAA+F;IAC/F,iGAAiG;IACjG,kGAAkG;IAClG,6BAA6B;IAC7B,GAAG,CAAC,GAAG,CAAC,yCAAyC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC7D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAA;QAE3C,+FAA+F;QAC/F,sFAAsF;QACtF,uFAAuF;QACvF,MAAM,mBAAmB,GAAG,SAAS,CAAC,YAAY,EAAE,mBAAmB,CAAA;QACvE,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC;YAC3C,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI;YAC3B,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC;YACpC,WAAW;YACX,SAAS,EAAE,mBAAmB,EAAE,SAAS;gBACvC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,mBAAmB,CAAC,SAAU,CAAC,EAAE,CAAuC;gBAClF,CAAC,CAAC,SAAS;SACd,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX;gBACE,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aACxF,EACD,IAAI,CAAC,MAAM,CACZ,CAAA;QACH,CAAC;QAED,6EAA6E;QAC7E,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,CAAC;YAC3D,OAAO,CAAC,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAClF,IAAI,CAAC,QAAQ;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAA;QACrE,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PersistenceMethodTable } from './rpc.js';
|
|
2
|
+
/**
|
|
3
|
+
* The mothership-mode persistence allow-list: the core domain repositories plus the
|
|
4
|
+
* workspace-scoped reads a board load (`GET /workspaces/:id`) and an execution exercise.
|
|
5
|
+
* Every method here binds to an account via its {@link ScopeRule} so a call outside the
|
|
6
|
+
* machine token's scope is refused as 404.
|
|
7
|
+
*
|
|
8
|
+
* The cross-service board-composition reads keyed on `serviceIds[]`/`accountId`
|
|
9
|
+
* (`listByServices`, `serviceRepository.listByIds`/`listByAccount`, `countByServiceIds`) and the
|
|
10
|
+
* entity-id-keyed `blockRepository.findById` are allow-listed here too, each bound by the
|
|
11
|
+
* {@link ScopeRule} `serviceList` / `block` / `account` kinds that resolve the entity's owning
|
|
12
|
+
* account server-side before the scope check.
|
|
13
|
+
*
|
|
14
|
+
* Still EXCLUDED (added in later gate slices, with their own scope rules, or kept
|
|
15
|
+
* mothership-internal):
|
|
16
|
+
* - `subscriptionActivationRepository.deleteByExecution` — the activation row is the local
|
|
17
|
+
* `node:sqlite` bucket (per the per-repo checklist), not the remote surface, so it is not
|
|
18
|
+
* exposed here.
|
|
19
|
+
* - Global sweeper methods (`listStale`, `deleteOlderThan`) and high-impact unscoped ops
|
|
20
|
+
* (`workspaceRepository.delete`, `accountRepository.create`).
|
|
21
|
+
*
|
|
22
|
+
* Admin-gated mutations are also EXCLUDED here. The RPC dispatches over the raw repository,
|
|
23
|
+
* bypassing the service layer that normally enforces per-user role checks — e.g.
|
|
24
|
+
* `AccountService.requireAdmin` guards `accountRepository.rename`/`updateSettings` and
|
|
25
|
+
* `membershipRepository.upsert`/`remove`. A machine token is scoped to whole ACCOUNTS, not to
|
|
26
|
+
* a role within them, so exposing those repo methods would let any account member self-promote
|
|
27
|
+
* to admin or rewrite memberships over the wire. They stay mothership-internal until a later
|
|
28
|
+
* slice adds a role dimension to the scope (or routes them through the service). Only the
|
|
29
|
+
* account/membership READS a board load needs are remotely callable. Board-level mutations
|
|
30
|
+
* (`workspaceRepository.rename`/`setDescription`, block/pipeline/execution CRUD) are
|
|
31
|
+
* member-level in the service layer, so they remain. The board mutations that stay OUT are
|
|
32
|
+
* `workspaceRepository.setAccessMode` (the access-mode flip) and `linkAccount` (the legacy-board
|
|
33
|
+
* auto-heal that adopts a board into an account) — both are `members.manage` (admin-tier), so like
|
|
34
|
+
* the account/membership admin mutations they must not be reachable over the role-blind machine RPC.
|
|
35
|
+
*/
|
|
36
|
+
export declare const REMOTE_PERSISTENCE_METHODS: PersistenceMethodTable;
|
|
37
|
+
//# sourceMappingURL=rpc-allowlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-allowlist.d.ts","sourceRoot":"","sources":["../../src/persistence/rpc-allowlist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAgBtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,0BAA0B,EAAE,sBAo1BxC,CAAA"}
|