@rubytech/create-maxy-code 0.1.561 → 0.1.563
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/package.json +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/datetime-inject.test.sh +10 -0
- package/payload/platform/plugins/admin/hooks/__tests__/mailbox-inject.test.sh +15 -2
- package/payload/platform/plugins/admin/hooks/__tests__/preference-consult-directive.test.sh +6 -0
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-directive.test.sh +10 -0
- package/payload/platform/plugins/admin/hooks/datetime-inject.sh +10 -0
- package/payload/platform/plugins/admin/hooks/mailbox-inject.sh +14 -0
- package/payload/platform/plugins/admin/hooks/preference-consult-directive.sh +9 -0
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-directive.sh +10 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +21 -11
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +11 -0
- package/payload/platform/plugins/cloudflare/bin/portal-enrol.mjs +19 -5
- package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +6 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +77 -6
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-session-grant.test.ts +39 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visit-status-write.test.ts +176 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visits-scope.test.ts +112 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +23 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +94 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +31 -4
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visit-status.ts +136 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visits.ts +93 -0
- package/payload/platform/plugins/docs/references/deployment.md +14 -8
- package/payload/platform/plugins/docs/references/internals.md +2 -0
- package/payload/platform/plugins/docs/references/platform.md +4 -2
- package/payload/platform/scripts/__tests__/public-prompt-gate-registered.test.sh +114 -0
- package/payload/platform/scripts/smoke-boot-services.sh +14 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +26 -10
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +16 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-prompt-surface.d.ts +56 -0
- package/payload/platform/services/claude-session-manager/dist/public-prompt-surface.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/public-prompt-surface.js +155 -0
- package/payload/platform/services/claude-session-manager/dist/public-prompt-surface.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts +6 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +4 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +45 -27
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/agents/public/IDENTITY.md +3 -3
- package/payload/server/maxy-edge.js +302 -33
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-DLogIsJT.js → AdminLoginScreens-C6e5jf0S.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-C6e5jf0S.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-C6e5jf0S.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DStA0lfm.js +3 -0
- package/payload/server/public/assets/AdminShell-DStA0lfm.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DStA0lfm.js.gz +0 -0
- package/payload/server/public/assets/{activity-AVJSFESV.js → activity--yyBcNfB.js} +1 -1
- package/payload/server/public/assets/activity--yyBcNfB.js.br +0 -0
- package/payload/server/public/assets/activity--yyBcNfB.js.gz +0 -0
- package/payload/server/public/assets/{admin-eFgbld42.js → admin-Dr6Jwe7W.js} +1 -1
- package/payload/server/public/assets/admin-Dr6Jwe7W.js.br +0 -0
- package/payload/server/public/assets/admin-Dr6Jwe7W.js.gz +0 -0
- package/payload/server/public/assets/{agents-CoWLZMf7.js → agents-odyVOb5E.js} +1 -1
- package/payload/server/public/assets/agents-odyVOb5E.js.br +0 -0
- package/payload/server/public/assets/agents-odyVOb5E.js.gz +0 -0
- package/payload/server/public/assets/{browser-C6K66_fw.js → browser-D1K_MoHt.js} +1 -1
- package/payload/server/public/assets/browser-D1K_MoHt.js.br +0 -0
- package/payload/server/public/assets/browser-D1K_MoHt.js.gz +0 -0
- package/payload/server/public/assets/{calendar-Dnw_cP4b.js → calendar-jqh9U7Ic.js} +1 -1
- package/payload/server/public/assets/calendar-jqh9U7Ic.js.br +0 -0
- package/payload/server/public/assets/calendar-jqh9U7Ic.js.gz +0 -0
- package/payload/server/public/assets/chat-QQHBdVor.js +1 -0
- package/payload/server/public/assets/chat-QQHBdVor.js.br +0 -0
- package/payload/server/public/assets/chat-QQHBdVor.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DwTXgKwr.js +1 -0
- package/payload/server/public/assets/clock-DOmh9iKX.js +1 -0
- package/payload/server/public/assets/clock-DOmh9iKX.js.br +0 -0
- package/payload/server/public/assets/{copy-kuNM0Etw.js → copy-DkuHwkaB.js} +1 -1
- package/payload/server/public/assets/copy-DkuHwkaB.js.br +0 -0
- package/payload/server/public/assets/copy-DkuHwkaB.js.gz +0 -0
- package/payload/server/public/assets/data-DYmTNqrb.js +1 -0
- package/payload/server/public/assets/data-DYmTNqrb.js.br +0 -0
- package/payload/server/public/assets/data-DYmTNqrb.js.gz +0 -0
- package/payload/server/public/assets/{file-text-BWkobrcx.js → file-text-C6o_NRjj.js} +1 -1
- package/payload/server/public/assets/file-text-C6o_NRjj.js.br +0 -0
- package/payload/server/public/assets/file-text-C6o_NRjj.js.gz +0 -0
- package/payload/server/public/assets/{graph-BGjTL5Vz.js → graph-BN30v5hJ.js} +1 -1
- package/payload/server/public/assets/graph-BN30v5hJ.js.br +0 -0
- package/payload/server/public/assets/graph-BN30v5hJ.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-Dvc5Kw_r.js → graph-labels-DHFyNXQt.js} +1 -1
- package/payload/server/public/assets/graph-labels-DHFyNXQt.js.br +0 -0
- package/payload/server/public/assets/graph-labels-DHFyNXQt.js.gz +0 -0
- package/payload/server/public/assets/{operator-CzBGv_he.js → operator-DwFYA4Fp.js} +1 -1
- package/payload/server/public/assets/operator-DwFYA4Fp.js.br +0 -0
- package/payload/server/public/assets/operator-DwFYA4Fp.js.gz +0 -0
- package/payload/server/public/assets/{page-DaySqamH.js → page-BALVRssF.js} +1 -1
- package/payload/server/public/assets/page-BALVRssF.js.br +0 -0
- package/payload/server/public/assets/page-BALVRssF.js.gz +0 -0
- package/payload/server/public/assets/{page-BIY4Ku8Q.js → page-CEWIP3VF.js} +1 -1
- package/payload/server/public/assets/page-CEWIP3VF.js.br +0 -0
- package/payload/server/public/assets/page-CEWIP3VF.js.gz +0 -0
- package/payload/server/public/assets/play-Bg-BY_oj.js +1 -0
- package/payload/server/public/assets/play-Bg-BY_oj.js.br +0 -0
- package/payload/server/public/assets/play-Bg-BY_oj.js.gz +0 -0
- package/payload/server/public/assets/{public-pwDSvhBv.js → public-Ceb0n7Km.js} +1 -1
- package/payload/server/public/assets/public-Ceb0n7Km.js.br +0 -0
- package/payload/server/public/assets/public-Ceb0n7Km.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-B6s7tkEt.js → rotate-ccw-CDYdx91V.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-CDYdx91V.js.gz +0 -0
- package/payload/server/public/assets/{routines-CFlyRdYg.js → routines-DwNTih0y.js} +1 -1
- package/payload/server/public/assets/routines-DwNTih0y.js.br +0 -0
- package/payload/server/public/assets/routines-DwNTih0y.js.gz +0 -0
- package/payload/server/public/assets/{skills-C45kfL_Q.js → skills-TIDCdOLQ.js} +1 -1
- package/payload/server/public/assets/skills-TIDCdOLQ.js.br +0 -0
- package/payload/server/public/assets/skills-TIDCdOLQ.js.gz +0 -0
- package/payload/server/public/assets/{tasks-BwoCTCu5.js → tasks-eTXvaWnd.js} +1 -1
- package/payload/server/public/assets/tasks-eTXvaWnd.js.br +0 -0
- package/payload/server/public/assets/tasks-eTXvaWnd.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-B3bthSzx.js → triangle-alert-JwLSrj17.js} +1 -1
- package/payload/server/public/assets/triangle-alert-JwLSrj17.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-JwLSrj17.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-BzJAkFEb.js → useCopyFeedback-DjTkNw2p.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-DjTkNw2p.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-DjTkNw2p.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-BsBzbWaf.css +1 -0
- package/payload/server/public/assets/useMediaQuery-BsBzbWaf.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-BsBzbWaf.css.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-D8VDA0RN.js +14 -0
- package/payload/server/public/assets/useMediaQuery-D8VDA0RN.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-D8VDA0RN.js.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-_qI_BAOo.js → useVoiceRecorder-B8vxObZG.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-B8vxObZG.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-B8vxObZG.js.gz +0 -0
- package/payload/server/public/assets/{wrench-Bqux9jaw.js → wrench-DutUiRu7.js} +1 -1
- package/payload/server/public/assets/wrench-DutUiRu7.js.br +0 -0
- package/payload/server/public/assets/wrench-DutUiRu7.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +13 -13
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +7 -7
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +1118 -636
- package/payload/server/public/assets/AdminLoginScreens-DLogIsJT.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-DLogIsJT.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-B67tPTyE.js +0 -2
- package/payload/server/public/assets/AdminShell-B67tPTyE.js.br +0 -0
- package/payload/server/public/assets/AdminShell-B67tPTyE.js.gz +0 -0
- package/payload/server/public/assets/activity-AVJSFESV.js.br +0 -0
- package/payload/server/public/assets/activity-AVJSFESV.js.gz +0 -0
- package/payload/server/public/assets/admin-eFgbld42.js.br +0 -0
- package/payload/server/public/assets/admin-eFgbld42.js.gz +0 -0
- package/payload/server/public/assets/agents-CoWLZMf7.js.br +0 -0
- package/payload/server/public/assets/agents-CoWLZMf7.js.gz +0 -0
- package/payload/server/public/assets/browser-C6K66_fw.js.br +0 -0
- package/payload/server/public/assets/browser-C6K66_fw.js.gz +0 -0
- package/payload/server/public/assets/calendar-Dnw_cP4b.js.br +0 -0
- package/payload/server/public/assets/calendar-Dnw_cP4b.js.gz +0 -0
- package/payload/server/public/assets/chat-Cm0fkpg1.js +0 -1
- package/payload/server/public/assets/chat-Cm0fkpg1.js.br +0 -0
- package/payload/server/public/assets/chat-Cm0fkpg1.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-CjRH-BtF.js +0 -1
- package/payload/server/public/assets/chevron-left-CjRH-BtF.js.br +0 -0
- package/payload/server/public/assets/clock-wbYEt1kM.js +0 -1
- package/payload/server/public/assets/clock-wbYEt1kM.js.br +0 -0
- package/payload/server/public/assets/clock-wbYEt1kM.js.gz +0 -0
- package/payload/server/public/assets/copy-kuNM0Etw.js.br +0 -0
- package/payload/server/public/assets/copy-kuNM0Etw.js.gz +0 -0
- package/payload/server/public/assets/data-c47T2NCd.js +0 -1
- package/payload/server/public/assets/data-c47T2NCd.js.br +0 -1
- package/payload/server/public/assets/data-c47T2NCd.js.gz +0 -0
- package/payload/server/public/assets/file-text-BWkobrcx.js.br +0 -0
- package/payload/server/public/assets/file-text-BWkobrcx.js.gz +0 -0
- package/payload/server/public/assets/graph-BGjTL5Vz.js.br +0 -0
- package/payload/server/public/assets/graph-BGjTL5Vz.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-Dvc5Kw_r.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Dvc5Kw_r.js.gz +0 -0
- package/payload/server/public/assets/operator-CzBGv_he.js.br +0 -0
- package/payload/server/public/assets/operator-CzBGv_he.js.gz +0 -0
- package/payload/server/public/assets/page-BIY4Ku8Q.js.br +0 -0
- package/payload/server/public/assets/page-BIY4Ku8Q.js.gz +0 -0
- package/payload/server/public/assets/page-DaySqamH.js.br +0 -0
- package/payload/server/public/assets/page-DaySqamH.js.gz +0 -0
- package/payload/server/public/assets/play-C8RA52_i.js +0 -1
- package/payload/server/public/assets/play-C8RA52_i.js.br +0 -0
- package/payload/server/public/assets/play-C8RA52_i.js.gz +0 -0
- package/payload/server/public/assets/public-pwDSvhBv.js.br +0 -0
- package/payload/server/public/assets/public-pwDSvhBv.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-B6s7tkEt.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-B6s7tkEt.js.gz +0 -0
- package/payload/server/public/assets/routines-CFlyRdYg.js.br +0 -0
- package/payload/server/public/assets/routines-CFlyRdYg.js.gz +0 -0
- package/payload/server/public/assets/skills-C45kfL_Q.js.br +0 -0
- package/payload/server/public/assets/skills-C45kfL_Q.js.gz +0 -0
- package/payload/server/public/assets/tasks-BwoCTCu5.js.br +0 -0
- package/payload/server/public/assets/tasks-BwoCTCu5.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-B3bthSzx.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-B3bthSzx.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-BzJAkFEb.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-BzJAkFEb.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DJ6XeNN7.js +0 -14
- package/payload/server/public/assets/useMediaQuery-DJ6XeNN7.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DJ6XeNN7.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DW_xRrMl.css +0 -1
- package/payload/server/public/assets/useMediaQuery-DW_xRrMl.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DW_xRrMl.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-_qI_BAOo.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-_qI_BAOo.js.gz +0 -0
- package/payload/server/public/assets/wrench-Bqux9jaw.js.br +0 -0
- package/payload/server/public/assets/wrench-Bqux9jaw.js.gz +0 -0
package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visits.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Handler, Logger, PortalEnv } from './_lib/types'
|
|
2
|
+
import { readSessionCookie, resolveSession } from './_lib/session'
|
|
3
|
+
import { q } from './_lib/log'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One published visit, as an account's own page renders it.
|
|
7
|
+
*
|
|
8
|
+
* The ontology's own fields (`schema-construction.md`) and the portal person the
|
|
9
|
+
* visit is assigned to, and nothing else. A job sheet's contents are the
|
|
10
|
+
* account's to design, and they are files, which the Task 1910 exchange already
|
|
11
|
+
* carries — so nothing of theirs belongs in this shape.
|
|
12
|
+
*/
|
|
13
|
+
export interface VisitRow {
|
|
14
|
+
visitId: string
|
|
15
|
+
ownerId: string
|
|
16
|
+
jobId: string
|
|
17
|
+
status: string
|
|
18
|
+
startDate: string
|
|
19
|
+
purpose: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The visits a signed-in person may read.
|
|
24
|
+
*
|
|
25
|
+
* TWO FILTERS, BOTH SERVER-SIDE, NEITHER REACHABLE FROM THE REQUEST. The
|
|
26
|
+
* account comes from the baked-in var for the reason `types.ts` gives at
|
|
27
|
+
* PORTAL_ACCOUNT_ID; the owner filter is applied when, and only when, the
|
|
28
|
+
* person's scope is `own`, read off the `people` join. No request parameter
|
|
29
|
+
* names either one, so there is no widening a caller can ask for.
|
|
30
|
+
*
|
|
31
|
+
* THIS FUNCTION IS THE ONLY READER OF `recordScope`, and that is deliberate. A
|
|
32
|
+
* scope column with no reader would be an unused column rather than a boundary.
|
|
33
|
+
* It ships here rather than being left for each account to write in its own copy
|
|
34
|
+
* of this tree, because a gate written once per client is a gate got wrong once
|
|
35
|
+
* per client — and this is the boundary that lets the surface sit on the open
|
|
36
|
+
* web.
|
|
37
|
+
*/
|
|
38
|
+
export async function processVisits(
|
|
39
|
+
sessionId: string,
|
|
40
|
+
env: PortalEnv,
|
|
41
|
+
log: Logger,
|
|
42
|
+
nowMs: number,
|
|
43
|
+
): Promise<Handler> {
|
|
44
|
+
const session = await resolveSession(env.DB, sessionId, env.PORTAL_ACCOUNT_ID, nowMs)
|
|
45
|
+
if (!session) {
|
|
46
|
+
log('[data-portal] op=visits owner=none result=denied')
|
|
47
|
+
return { status: 401, payload: { ok: false, error: 'denied' } }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const scoped = session.recordScope === 'own'
|
|
51
|
+
// Read through the generation pointer, so a listing that races a push sees one
|
|
52
|
+
// generation whole rather than a half-built one — the same join `files.ts`
|
|
53
|
+
// makes against directory_state, for the same reason.
|
|
54
|
+
const sql =
|
|
55
|
+
`SELECT v.visitId AS visitId, v.ownerId AS ownerId, v.jobId AS jobId,
|
|
56
|
+
v.status AS status, v.startDate AS startDate, v.purpose AS purpose
|
|
57
|
+
FROM visits v
|
|
58
|
+
JOIN visits_state s
|
|
59
|
+
ON s.accountId = v.accountId AND s.currentGeneration = v.generation
|
|
60
|
+
WHERE v.accountId = ?` +
|
|
61
|
+
(scoped ? ' AND v.ownerId = ?' : '') +
|
|
62
|
+
' ORDER BY v.startDate ASC, v.visitId ASC'
|
|
63
|
+
const stmt = env.DB.prepare(sql)
|
|
64
|
+
const bound = scoped
|
|
65
|
+
? stmt.bind(env.PORTAL_ACCOUNT_ID, session.ownerId)
|
|
66
|
+
: stmt.bind(env.PORTAL_ACCOUNT_ID)
|
|
67
|
+
const rows = await bound.all<VisitRow>()
|
|
68
|
+
const visits = rows.results ?? []
|
|
69
|
+
|
|
70
|
+
// Counts and the scope, never a visitId or a purpose: those are a real
|
|
71
|
+
// person's job, and a Pages log is not where they belong.
|
|
72
|
+
log(
|
|
73
|
+
`[data-portal] op=visits owner=${q(session.ownerId)} account=${q(session.accountId)} ` +
|
|
74
|
+
`scope=${session.recordScope} visits=${visits.length} result=ok`,
|
|
75
|
+
)
|
|
76
|
+
return { status: 200, payload: { ok: true, visits } }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface PagesContext {
|
|
80
|
+
request: Request
|
|
81
|
+
env: PortalEnv
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function onRequestGet(context: PagesContext): Promise<Response> {
|
|
85
|
+
const sessionId = readSessionCookie(context.request.headers.get('cookie')) ?? ''
|
|
86
|
+
const { status, payload } = await processVisits(
|
|
87
|
+
sessionId,
|
|
88
|
+
context.env,
|
|
89
|
+
(line) => console.log(line),
|
|
90
|
+
Date.now(),
|
|
91
|
+
)
|
|
92
|
+
return Response.json(payload, { status })
|
|
93
|
+
}
|
|
@@ -201,11 +201,11 @@ The logs will show which service failed to start and why. Common causes:
|
|
|
201
201
|
Each installed brand runs two per-brand `--user` systemd units (earlier platform fixes + — unit filenames are prefixed with the brand's `hostname` so two brands on the same device never share a unit file):
|
|
202
202
|
|
|
203
203
|
- `{hostname}.service` — the admin + public HTTP server on `127.0.0.1:19201` (public port + 1). Restarted by the upgrade flow; short downtime is expected during steps 8→11 of an upgrade. An earlier fix: the unit carries two port env vars — `PORT=<public>` (canonical public port, read by the upgrade detector) and `MAXY_UI_INTERNAL_PORT=<public+1>` (the port maxy-ui actually binds).
|
|
204
|
-
- `{hostname}-edge.service` — the always-on public listener on the configured port (default 19200). Reverse-proxies HTTP to the main brand service and handles `/websockify` (VNC) WebSocket upgrades locally. An earlier fix: also hosts `/api/admin/actions/*` and `/api/admin/version*` — the Software Update modal's own routes — so
|
|
204
|
+
- `{hostname}-edge.service` — the always-on public listener on the configured port (default 19200). Reverse-proxies HTTP to the main brand service and handles `/websockify` (VNC) WebSocket upgrades locally. An earlier fix: also hosts `/api/admin/actions/*` and `/api/admin/version*` — the Software Update modal's own routes — so they survive the brand service's restart window. It is restarted by the upgrade flow too (`packages/create-maxy-code/src/index.ts:5143`, after the brand service is stopped and before it is restarted), so the update stream drops near the end of every run and resumes by byte offset. It is not a connection that survives; the log file is what survives, and the browser's `EventSource` replays `Last-Event-ID` to pick the tail back up. The operator views the device's Chromium in the admin UI via the standalone `/browser` page (peer to `/graph` and `/data`) and on the Claude sign-in screen; both render CDP screencast frames over `/cdp-screencast`, not the framebuffer. Virtual-mode Chromium is headless, so nothing renders onto the X display and the `/websockify` upgrade has no remaining consumer; deleting that stack is separate work.
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
The upgrade runs as a detached action: a `systemd-run --user --unit=maxy-action-<actionId> --collect` transient unit per invocation, with stdout+stderr persisted to `~/.<brand>/logs/actions/<actionId>.log` and streamed to the UI via SSE. The unit has its own cgroup, so it outlives both service restarts the installer performs. Its final log line is `[action-exit] code=<n>`, written by the wrapper, which is how the exit code survives a unit that `--collect` has already reaped. A sidecar `~/.<brand>/logs/actions/<actionId>.json` holds the package, start time and pre-upgrade version, so a modal reopened after a reload can still report what changed. No boot-time service file exists for these. Cloudflare setup is not an action; it runs PTY-native from admin chat.
|
|
207
207
|
|
|
208
|
-
If an action looks stuck, read
|
|
208
|
+
If an action looks stuck, read `~/.<brand>/logs/actions/<actionId>.log` directly for the full output, or `journalctl --user --identifier=maxy-action-<actionId>` for systemd's record. The lifecycle lines are tagged `[admin-action]` and keyed by `actionId`; they land in `~/.<brand>/logs/edge.log`, not `server.log`, because these routes run on the edge process.
|
|
209
209
|
|
|
210
210
|
## Linux laptops: snap-confined Chromium replacement
|
|
211
211
|
|
|
@@ -314,14 +314,20 @@ Empty output from step 3 = brand.json resolved cleanly and the badge reflects th
|
|
|
314
314
|
|
|
315
315
|
## Upgrading
|
|
316
316
|
|
|
317
|
-
|
|
317
|
+
There are two ways to upgrade, and both run the same installer.
|
|
318
|
+
|
|
319
|
+
From the dashboard, press the download icon in the sidebar header (see below). From chat, ask {{productName}}: "Upgrade {{productName}}." The platform checks the current device identity (hostname and port via `system-status`), then re-runs the installer with explicit `--hostname` and `--port` flags to preserve them across the upgrade.
|
|
318
320
|
|
|
319
321
|
The docs plugin (this plugin) is upgraded in the same step — you always have the documentation that matches your installed version.
|
|
320
322
|
|
|
321
|
-
###
|
|
323
|
+
### Upgrading from the dashboard
|
|
324
|
+
|
|
325
|
+
The sidebar header shows the version you are running, under the product name, at all times. When a newer one is published a download icon appears beside it. There is no icon when you are already up to date, so the icon appearing is itself the news. If you work with the sidebar collapsed to the narrow rail, the version and the icon are hidden with the rest of the header text and a small coloured dot on the brand icon carries the same signal.
|
|
326
|
+
|
|
327
|
+
Pressing the icon opens the Software Update window, which shows the version you have against the version available and an Update button. Pressing Update runs the installer and streams its output into the window as it happens.
|
|
322
328
|
|
|
323
|
-
|
|
329
|
+
Closing the window does not cancel the upgrade. The installer runs in its own background unit, so it keeps going whether or not anything is watching, and reopening the window reattaches to the run in progress.
|
|
324
330
|
|
|
325
|
-
The upgrade
|
|
331
|
+
**The connection drops near the end of every upgrade, and that is expected.** The installer restarts the server as its last step, which cuts the browser's connection to it. The window says "Reconnecting" while that happens, then picks the output back up from exactly where it left off. Nothing is lost and nothing needs restarting. When it finishes, the window reports the exit code and whether the version actually moved.
|
|
326
332
|
|
|
327
|
-
The
|
|
333
|
+
The window reports a genuine failure in two shapes worth knowing. If the installer exits non-zero it says so with the code. If it exits cleanly but the version did not change, it says that too, rather than claiming success.
|
|
@@ -238,6 +238,8 @@ There is exactly one place each datum is read from, and every subsystem reads it
|
|
|
238
238
|
- **Default agent + account id** come from the canonical account config `data/accounts/<id>/account.json`, resolved via `resolveAccount` / `resolveDefaultAgentSlug` / `getDefaultAccountId` (`app/lib/claude-agent/account.ts`). The UI server's bare-root handler and branding loader read it through these helpers — never from `~/.<brand>/account.json`, which nothing writes. A `null` default means a genuinely unset `defaultAgent`; the root logs `[public-root] op=serve-default slug=<s>` on success and `op=no-default` only when the canonical default is truly empty.
|
|
239
239
|
- **Identity files** (IDENTITY.md, SOUL.md, KNOWLEDGE.md) come from `agents/<slug>/` — keyed on the agent's slug, never the literal role. A public agent renamed to a slug `≠ "public"` (e.g. `maxy-info`) spawns from `agents/maxy-info/`. Admin reads `agents/admin/`. The spawn composer and the standing reachability audit resolve this directory through one shared function, `resolveAgentIdentityDir(accountDir, role, slug)` (`claude-session-manager/src/agent-identity-locator.ts`), so the path the audit vouches for is byte-identical to the path the spawn reads — the audit's `reachable=true` implies the spawn will find the files, and a slug whose files are misplaced is reported `reachable=false reason=files-missing file=<path>` without a visitor request.
|
|
240
240
|
|
|
241
|
+
**What a public block contains.** A `role='public'` compose emits `<identity>`, `<soul>`, `<platform-boundary>`, `<data-stewardship>` and `<knowledge>`, and nothing else. The `<host>` section every other role gets is omitted: hostname, LAN IPv4, admin URL and tunnel URL are facts about the operator's machine, and a visitor's agent holds only what its author wrote. The two standing directives stay because they constrain behaviour rather than stating extractable facts. `op=public-persona-composed … hostBytes=0` is the per-spawn proof; non-zero on a public spawn is the regression signal, readable without reproducing a visitor turn.
|
|
242
|
+
|
|
241
243
|
Which account is `<id>`? The slug is the address, and the address names the account. `resolvePublicAddressFromDisk` (`platform/ui/app/lib/claude-agent/public-address.ts`) walks every valid account for an active agent at the requested slug: exactly one claimant serves; the house serves when it is among several claimants and the others are refused by name; two or more non-house claimants serve nobody. The bare root `/` carries no slug and stays the house's door with the house's `defaultAgent`. The four public surfaces — the `/{slug}` page, `POST /api/chat`, `POST /api/session` and the visitor transcript reader — share that one resolver, and the resolved account rides `agentAccountId` to `/public-spawn`, which re-scopes the spawn onto it. A visitor's uploads follow the same account, and the reader locates them from the session's own sidecar `accountId` rather than re-deriving them from the slug, because a slug's owner can change after the session ran. Slugs are not unique across accounts, so a collision is reported on every refusal (`[webchat] op=address-collision`) and counted on every run of the `webchat-address-audit` loop.
|
|
242
244
|
|
|
243
245
|
### Observability
|
|
@@ -167,9 +167,11 @@ The Data search panel ranks results by combining vector similarity with keyword
|
|
|
167
167
|
|
|
168
168
|
## Software Update and Cloudflare Setup
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
Cloudflare setup runs on the native Claude Code PTY surface in admin chat: there is no Cloudflare setup form, the agent invokes the relevant Bash command directly and its stdout streams into chat verbatim.
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
Software update has two doors. The PTY one is the same shape: the agent runs the installer via Bash and its stdout streams into chat. The dashboard one is a modal over the edge-hosted `/api/admin/actions` routes, which run the installer as a `systemd-run` transient unit and stream its log back by byte offset. Both re-run the same installer; neither mutates state directly.
|
|
173
|
+
|
|
174
|
+
- **Software update.** Re-run the installer (`npx -y @rubytech/create-<brand>@latest`), from a shell, from admin chat via the `upgrade` skill, or from the dashboard control in the sidebar brand head. The brand head shows the installed version at all times and grows a download icon only while `updateAvailable` is true.
|
|
173
175
|
- **Cloudflare setup.** Operator asks in chat; the agent invokes `cloudflared` directly via the Bash tool, following the numbered steps in `plugins/cloudflare/references/manual-setup.md`. cloudflared's stdout and stderr stream into the PTY; the OAuth URL printed by `cloudflared tunnel login` is linkified by the terminal so the operator clicks it and authorises Cloudflare in their own browser.
|
|
174
176
|
|
|
175
177
|
**Mid-turn stream-drop banners.** If a chat turn ends abruptly the bubble shows one of two messages depending on what actually happened. You see "Server is restarting — reconnect will happen automatically." only when the app server itself emits the restart signal — typically during a Software Update or a Cloudflare setup that re-launches the brand service. You see "Lost connection — retrying." when your browser's connection to the Pi dropped mid-stream while the server was still up — typically a flaky Wi-Fi moment or the tunnel hiccupping. Either way the chat resumes once the connection is back; the previously-rendered messages stay on screen so you don't lose context.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Task 2424 — every UserPromptSubmit hook must either carry the public gate or
|
|
3
|
+
# be on the inert list. A fifth injecting hook added without a gate emits no
|
|
4
|
+
# event and does not reproduce on demand: the only symptom is a stranger being
|
|
5
|
+
# told something about the operator.
|
|
6
|
+
#
|
|
7
|
+
# Both writers are scanned. provision-account-dir.sh writes the array at account
|
|
8
|
+
# creation; the account-settings-*.sh libs patch it onto accounts that already
|
|
9
|
+
# exist, which is the only path that reaches client sub-accounts. Of the four
|
|
10
|
+
# libs only mailbox-inject and public-surface touch this event — askgate patches
|
|
11
|
+
# PreToolUse and pdf-conformance patches PostToolUse, so the filter skipping
|
|
12
|
+
# them is correct rather than a broken parser.
|
|
13
|
+
#
|
|
14
|
+
# The guard is matched as a fixed string, never as a mention of the variable: a
|
|
15
|
+
# hook that merely READS MAXY_PUBLIC_ALLOWED_TOOLS is not gated by it, and
|
|
16
|
+
# counting it as gated is exactly the false green this test exists to avoid.
|
|
17
|
+
set -uo pipefail
|
|
18
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
PROV="$DIR/../lib/provision-account-dir.sh"
|
|
20
|
+
HOOKS_DIR="$DIR/../../plugins/admin/hooks"
|
|
21
|
+
GUARD='[ -n "${MAXY_PUBLIC_ALLOWED_TOOLS:-}" ]'
|
|
22
|
+
INERT="archive-ingest-surface-gate.sh public-tool-surface.sh"
|
|
23
|
+
PASS=0; FAIL=0
|
|
24
|
+
|
|
25
|
+
ok() { echo "PASS: $1"; PASS=$((PASS+1)); }
|
|
26
|
+
bad() { echo "FAIL: $1" >&2; FAIL=$((FAIL+1)); }
|
|
27
|
+
|
|
28
|
+
# Every hook script named inside the provision heredoc's UserPromptSubmit array.
|
|
29
|
+
# The script name is taken from the END of each `"command"` string, not from a
|
|
30
|
+
# `hooks/` prefix: provision writes `bash $HOOKS_PATH/<name>.sh`, so the literal
|
|
31
|
+
# directory never appears there and a prefix anchor silently matches nothing.
|
|
32
|
+
PROV_HOOKS=$(python3 - "$PROV" <<'PY'
|
|
33
|
+
import re, sys
|
|
34
|
+
src = open(sys.argv[1], encoding="utf-8").read()
|
|
35
|
+
m = re.search(r'"UserPromptSubmit"\s*:\s*\[(.*?)\n \]', src, re.S)
|
|
36
|
+
if not m:
|
|
37
|
+
print("")
|
|
38
|
+
sys.exit(0)
|
|
39
|
+
cmds = re.findall(r'"command"\s*:\s*"([^"]*)"', m.group(1))
|
|
40
|
+
names = [n.group(1) for n in (re.search(r'([A-Za-z0-9_.-]+\.sh)\s*$', c.strip()) for c in cmds) if n]
|
|
41
|
+
print("\n".join(sorted(set(names))))
|
|
42
|
+
PY
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Every hook script named by a backfill lib that patches the same array. Read
|
|
46
|
+
# only from the `_<NAME>_CMD=` constant each lib registers, not from every `.sh`
|
|
47
|
+
# in the file: these libs name their siblings in prose, and a bare `.sh` sweep
|
|
48
|
+
# turns those comments into phantom registrations.
|
|
49
|
+
BACKFILL_HOOKS=""
|
|
50
|
+
for lib in "$DIR"/../lib/account-settings-*.sh; do
|
|
51
|
+
grep -q 'hooks\.UserPromptSubmit' "$lib" || continue
|
|
52
|
+
cmd_names=$(grep -oE "^_[A-Z0-9_]+_CMD='[^']*'" "$lib" | grep -oE "[A-Za-z0-9_.-]+\.sh'$" | tr -d "'")
|
|
53
|
+
if [ -z "$cmd_names" ]; then
|
|
54
|
+
bad "$(basename "$lib") patches UserPromptSubmit but names no _<NAME>_CMD script — the parser cannot see what it registers"
|
|
55
|
+
fi
|
|
56
|
+
BACKFILL_HOOKS="$BACKFILL_HOOKS
|
|
57
|
+
$cmd_names"
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
ALL=$(printf '%s\n%s\n' "$PROV_HOOKS" "$BACKFILL_HOOKS" | grep -v '^$' | sort -u)
|
|
61
|
+
|
|
62
|
+
if [ -z "$ALL" ]; then
|
|
63
|
+
bad "no UserPromptSubmit hooks found in either writer — the parser is broken, not the tree"
|
|
64
|
+
else
|
|
65
|
+
ok "found $(printf '%s\n' "$ALL" | wc -l | tr -d ' ') registered UserPromptSubmit hooks across both writers"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
for h in $ALL; do
|
|
69
|
+
case " $INERT " in
|
|
70
|
+
*" $h "*) ok "$h is on the inert list"; continue ;;
|
|
71
|
+
esac
|
|
72
|
+
if [ ! -f "$HOOKS_DIR/$h" ]; then
|
|
73
|
+
bad "$h is registered but has no script at $HOOKS_DIR/$h"
|
|
74
|
+
elif grep -qF "$GUARD" "$HOOKS_DIR/$h"; then
|
|
75
|
+
ok "$h carries the public gate"
|
|
76
|
+
else
|
|
77
|
+
bad "$h is registered on UserPromptSubmit with no public gate and is not inert"
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
# The guard and the inert list each exist twice: here, and as exported constants
|
|
82
|
+
# in public-prompt-surface.ts, which the standing census matches against. Two
|
|
83
|
+
# hand-maintained copies of one literal is the drift class that bites silently,
|
|
84
|
+
# so assert them equal. Divergence is not silent here — the census would FATAL
|
|
85
|
+
# every hook on every account and fail every install smoke run — but it would be
|
|
86
|
+
# a false alarm, and the cause would not be obvious from that output.
|
|
87
|
+
CENSUS_TS="$DIR/../../services/claude-session-manager/src/public-prompt-surface.ts"
|
|
88
|
+
if [ ! -f "$CENSUS_TS" ]; then
|
|
89
|
+
bad "the census module is not at $CENSUS_TS — this test can no longer check the shared literals"
|
|
90
|
+
else
|
|
91
|
+
if grep -qF "export const PUBLIC_GATE_GUARD = '$GUARD'" "$CENSUS_TS"; then
|
|
92
|
+
ok "the census module's PUBLIC_GATE_GUARD matches the guard this test greps for"
|
|
93
|
+
else
|
|
94
|
+
bad "PUBLIC_GATE_GUARD in $CENSUS_TS differs from this test's GUARD — the two would disagree about what 'gated' means"
|
|
95
|
+
fi
|
|
96
|
+
for h in $INERT; do
|
|
97
|
+
if grep -qF "'$h'," "$CENSUS_TS" || grep -qF "'$h'" "$CENSUS_TS"; then
|
|
98
|
+
ok "the census module lists $h as inert too"
|
|
99
|
+
else
|
|
100
|
+
bad "$h is inert here but not in $CENSUS_TS — the census would FATAL on it"
|
|
101
|
+
fi
|
|
102
|
+
done
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# The path the standing census reads must stay the path provision writes.
|
|
106
|
+
if grep -qF 'ACCOUNT_SETTINGS="$ACCOUNT_DIR/.claude/settings.json"' "$PROV"; then
|
|
107
|
+
ok "the settings path the census reads is still the path provision writes"
|
|
108
|
+
else
|
|
109
|
+
bad "provision no longer writes .claude/settings.json — the census path is stale"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
echo "----"
|
|
113
|
+
echo "PASS=$PASS FAIL=$FAIL"
|
|
114
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -284,6 +284,20 @@ run_one() {
|
|
|
284
284
|
fi
|
|
285
285
|
done
|
|
286
286
|
|
|
287
|
+
# Task 2424 — a public-prompt-surface drift line means some account has a
|
|
288
|
+
# per-turn hook that will inject operator context into a visitor's turn. The
|
|
289
|
+
# census fires once at boot, inside this window. Scoped to this one tag rather
|
|
290
|
+
# than widening the generic `fatal ` regex above, which would newly fail this
|
|
291
|
+
# gate on unrelated subsystems' pre-existing drift lines.
|
|
292
|
+
local drift_line
|
|
293
|
+
drift_line="$(grep -m1 -F '[public-prompt-surface] op=drift FATAL' "$log_file" || true)"
|
|
294
|
+
if [ -n "$drift_line" ]; then
|
|
295
|
+
echo "[smoke] service=$name reason=public-prompt-surface-drift matched=$drift_line" >&2
|
|
296
|
+
echo "--- log ($log_file) ---" >&2
|
|
297
|
+
cat "$log_file" >&2
|
|
298
|
+
return 1
|
|
299
|
+
fi
|
|
300
|
+
|
|
287
301
|
echo "[smoke-boot] service=$name specialist-tool-drift=ok system-prompt-sentinels=ok identity-drift=ok boot=ok elapsed-ms=$elapsed_ms"
|
|
288
302
|
return 0
|
|
289
303
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAoB3B,OAAO,KAAK,EAAU,SAAS,EAAW,MAAM,YAAY,CAAA;AAK5D,OAAO,EAkBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAqBzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAoBlD,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAQlE;;;;;;;;;;;mFAWmF;AACnF,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GACvB,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,IAAI,CAE/C;AAED;;;;;;;;;;2EAU2E;AAC3E,wBAAgB,cAAc,CAC5B,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3C,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAAG,IAAI,CAOlD;AAsFD,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB;;oEAEgE;IAChE,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,WAAW,EAAE,kBAAkB,CAAA;IAC/B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;sBAEkB;IAClB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB;;;sCAGkC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;4EAGwE;IACxE,YAAY,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAA;CAC9C;AAsFD;;;;;;mEAMmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC9D;AAMD;;;;;;iBAMiB;AACjB,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAmCvF;AAID;;;;;;yBAMyB;AACzB,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAiCzD;AAwCD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAiGD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CASvG;AAUD,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,OAAO,GACxB,IAAI,CA4BN;AAkED;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AA8CD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -3502,7 +3502,13 @@ export function buildHttpApp(deps) {
|
|
|
3502
3502
|
return c.json({ error: 'spawn-failed', reason: composed.reason }, 503);
|
|
3503
3503
|
}
|
|
3504
3504
|
appendSegments.push(composed.block);
|
|
3505
|
-
|
|
3505
|
+
// Task 2424 — `hostBytes=0` is the healthy value here and the per-spawn
|
|
3506
|
+
// proof that a visitor's block carries no host addresses; non-zero is the
|
|
3507
|
+
// composer regressing, readable without reproducing a visitor turn.
|
|
3508
|
+
// `blockBytes` bounds the whole composed surface, so an unexpected growth
|
|
3509
|
+
// (a section reaching this path that should not) is visible as a number
|
|
3510
|
+
// rather than needing the block itself.
|
|
3511
|
+
deps.logger(`[rc-spawn] op=public-persona-composed slug=${rcAgentSlug} identityBytes=${composed.identityBytes} soulBytes=${composed.soulBytes} knowledgeBytes=${composed.knowledgeBytes} hostBytes=${composed.hostBytes} blockBytes=${Buffer.byteLength(composed.block, 'utf8')}`);
|
|
3506
3512
|
}
|
|
3507
3513
|
if (appendSegments.length > 0) {
|
|
3508
3514
|
argv.push('--append-system-prompt', appendSegments.join('\n\n'));
|
|
@@ -3678,6 +3684,20 @@ export function buildHttpApp(deps) {
|
|
|
3678
3684
|
// match to false — grep-able (`op=cwd-check` + `match=false`) with no
|
|
3679
3685
|
// live repro needed.
|
|
3680
3686
|
deps.logger(`[rc-spawn] op=cwd-check unitToken=${unitToken} resolved=${env.ACCOUNT_DIR} actual=${effectiveAccountDir} match=${env.ACCOUNT_DIR === effectiveAccountDir}`);
|
|
3687
|
+
// Task 2339 — the realised-surface hook's only input. `tool-allowlist` below
|
|
3688
|
+
// records the surface this spawn was GIVEN; nothing recorded the surface it
|
|
3689
|
+
// REALISES, so five tools ran under a one-tool allowlist and produced no
|
|
3690
|
+
// line. Stamped here rather than inside buildRcChildEnv so it lands after
|
|
3691
|
+
// the last argv push and the value is this spawn's final `--allowed-tools`
|
|
3692
|
+
// set. Public spawns only; its presence is the signal the hook keys on.
|
|
3693
|
+
//
|
|
3694
|
+
// Task 2424 — moved ABOVE the `tool-allowlist` line, which now reports this
|
|
3695
|
+
// value. It used to be stamped after, so the line could not see it. The four
|
|
3696
|
+
// per-turn hook gates also key on this variable, so its absence on a public
|
|
3697
|
+
// spawn is what `publicToolsEnv=0` names.
|
|
3698
|
+
if (publicLockdown) {
|
|
3699
|
+
env[PUBLIC_ALLOWED_TOOLS_ENV] = allowedToolsFromArgv(argv).join(',');
|
|
3700
|
+
}
|
|
3681
3701
|
// Task 2260 — the realised tool surface, on EVERY rc-spawn. /rc-spawn emitted
|
|
3682
3702
|
// no such line, which is why the incident session was invisible to every
|
|
3683
3703
|
// tool-surface audit. An admin spawn reports count=0 strictMcp=n, which is
|
|
@@ -3688,16 +3708,12 @@ export function buildHttpApp(deps) {
|
|
|
3688
3708
|
count: publicLockdown ? publicLockdown.allowedTools.length : 0,
|
|
3689
3709
|
strictMcp: publicLockdown !== null,
|
|
3690
3710
|
mode: effectiveRcPermissionMode,
|
|
3711
|
+
// Task 2424 — read back from the env actually stamped, not from the
|
|
3712
|
+
// allowlist computed above, so the line reports what reached the child.
|
|
3713
|
+
publicToolsEnv: (env[PUBLIC_ALLOWED_TOOLS_ENV] ?? '')
|
|
3714
|
+
.split(',')
|
|
3715
|
+
.filter((t) => t.length > 0).length,
|
|
3691
3716
|
}));
|
|
3692
|
-
// Task 2339 — the realised-surface hook's only input. `tool-allowlist` above
|
|
3693
|
-
// records the surface this spawn was GIVEN; nothing recorded the surface it
|
|
3694
|
-
// REALISES, so five tools ran under a one-tool allowlist and produced no
|
|
3695
|
-
// line. Stamped here rather than inside buildRcChildEnv so it lands after
|
|
3696
|
-
// the last argv push and the value is this spawn's final `--allowed-tools`
|
|
3697
|
-
// set. Public spawns only; its presence is the signal the hook keys on.
|
|
3698
|
-
if (publicLockdown) {
|
|
3699
|
-
env[PUBLIC_ALLOWED_TOOLS_ENV] = allowedToolsFromArgv(argv).join(',');
|
|
3700
|
-
}
|
|
3701
3717
|
deps.logger(`[rc-spawn] op=argv unitToken=${unitToken} cwd=${effectiveAccountDir} permissionMode=${effectiveRcPermissionMode} model=${effectiveRcModel ?? 'unset'} effort=${effectiveRcEffort ?? 'unset'} positionalBytes=${positionalBytes} voiceBytes=${voiceBytes} argv=${JSON.stringify([deps.claudeBin, ...argv])}`);
|
|
3702
3718
|
emitRcLife(deps.logger, 'argv', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
|
|
3703
3719
|
cwd: effectiveAccountDir,
|