@songsid/agend 2.3.5-alpha.3 → 2.3.5-alpha.5
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/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/accounts-view.d.ts +97 -0
- package/dist/accounts-view.js +116 -0
- package/dist/accounts-view.js.map +1 -0
- package/dist/agent-cli-instructions.md +1 -1
- package/dist/agent-credentials.d.ts +24 -0
- package/dist/agent-credentials.js +66 -0
- package/dist/agent-credentials.js.map +1 -0
- package/dist/agent-endpoint.d.ts +3 -1
- package/dist/agent-endpoint.js +13 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-runtime-api.d.ts +4 -0
- package/dist/agent-runtime-api.js +59 -0
- package/dist/agent-runtime-api.js.map +1 -0
- package/dist/agent-runtime-change.d.ts +76 -0
- package/dist/agent-runtime-change.js +114 -0
- package/dist/agent-runtime-change.js.map +1 -0
- package/dist/agent-workspace.d.ts +93 -0
- package/dist/agent-workspace.js +353 -0
- package/dist/agent-workspace.js.map +1 -0
- package/dist/auth-api.d.ts +27 -0
- package/dist/auth-api.js +168 -3
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/session-authorizations.d.ts +28 -4
- package/dist/authority/session-authorizations.js +63 -17
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/backend/antigravity.js +3 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/codex-footer-hints.d.ts +7 -0
- package/dist/backend/codex-footer-hints.js +41 -0
- package/dist/backend/codex-footer-hints.js.map +1 -0
- package/dist/backend/codex-metadata.d.ts +14 -0
- package/dist/backend/codex-metadata.js +45 -0
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex-quota-history.d.ts +7 -0
- package/dist/backend/codex-quota-history.js +57 -0
- package/dist/backend/codex-quota-history.js.map +1 -0
- package/dist/backend/codex-session-lookup.d.ts +6 -0
- package/dist/backend/codex-session-lookup.js +1 -1
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex-speed.d.ts +14 -0
- package/dist/backend/codex-speed.js +35 -0
- package/dist/backend/codex-speed.js.map +1 -0
- package/dist/backend/codex.d.ts +7 -0
- package/dist/backend/codex.js +85 -24
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/grok-weekly-reset.d.ts +24 -0
- package/dist/backend/grok-weekly-reset.js +95 -0
- package/dist/backend/grok-weekly-reset.js.map +1 -0
- package/dist/backend/grok.d.ts +30 -1
- package/dist/backend/grok.js +301 -54
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +3 -0
- package/dist/backend/kiro.js +50 -2
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/muse.js +5 -3
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/native-pane.d.ts +3 -1
- package/dist/backend/native-pane.js +2 -2
- package/dist/backend/native-pane.js.map +1 -1
- package/dist/backend/types.d.ts +13 -1
- package/dist/backend/types.js +3 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/build-provenance-cli.d.ts +3 -0
- package/dist/build-provenance-cli.js +11 -0
- package/dist/build-provenance-cli.js.map +1 -0
- package/dist/build-provenance.d.ts +20 -0
- package/dist/build-provenance.js +67 -0
- package/dist/build-provenance.js.map +1 -0
- package/dist/build-provenance.json +1 -0
- package/dist/cache-ledger.d.ts +95 -0
- package/dist/cache-ledger.js +276 -4
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-service.d.ts +5 -0
- package/dist/cache-service.js +16 -4
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.js +11 -3
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +51 -0
- package/dist/channel/adapters/telegram.js +235 -17
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +3 -3
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +2 -0
- package/dist/claude-auth-status.d.ts +48 -0
- package/dist/claude-auth-status.js +149 -0
- package/dist/claude-auth-status.js.map +1 -0
- package/dist/cli.js +138 -37
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +21 -1
- package/dist/config-validator.js.map +1 -1
- package/dist/cross-instance-notice.d.ts +10 -0
- package/dist/cross-instance-notice.js +67 -5
- package/dist/cross-instance-notice.js.map +1 -1
- package/dist/daemon.d.ts +70 -1
- package/dist/daemon.js +547 -25
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard-permissions.d.ts +8 -0
- package/dist/dashboard-permissions.js +16 -0
- package/dist/dashboard-permissions.js.map +1 -1
- package/dist/delivery-consumed-watch.d.ts +23 -1
- package/dist/delivery-consumed-watch.js +30 -3
- package/dist/delivery-consumed-watch.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +1 -1
- package/dist/delivery-reconciliation.js +1 -1
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/doctor.js +20 -9
- package/dist/doctor.js.map +1 -1
- package/dist/export-import.d.ts +7 -0
- package/dist/export-import.js +44 -10
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-context.d.ts +2 -0
- package/dist/fleet-manager.d.ts +362 -7
- package/dist/fleet-manager.js +1522 -91
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-windows-runtime.d.ts +8 -2
- package/dist/fleet-windows-runtime.js +93 -6
- package/dist/fleet-windows-runtime.js.map +1 -1
- package/dist/general-knowledge/skills/concepts/SKILL.md +425 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +5 -2
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +1 -0
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +2 -2
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +3 -1
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +41 -4
- package/dist/general-knowledge/skills/session-management/SKILL.md +1 -1
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +10 -10
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +31 -15
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/general-role.d.ts +1 -1
- package/dist/general-role.js +1 -0
- package/dist/general-role.js.map +1 -1
- package/dist/hub/admission.d.ts +28 -0
- package/dist/hub/admission.js +62 -0
- package/dist/hub/admission.js.map +1 -0
- package/dist/hub/attachments/limits.d.ts +20 -0
- package/dist/hub/attachments/limits.js +48 -0
- package/dist/hub/attachments/limits.js.map +1 -0
- package/dist/hub/attachments/store.d.ts +116 -0
- package/dist/hub/attachments/store.js +246 -0
- package/dist/hub/attachments/store.js.map +1 -0
- package/dist/hub/audit/index.d.ts +62 -0
- package/dist/hub/audit/index.js +344 -0
- package/dist/hub/audit/index.js.map +1 -0
- package/dist/hub/browser-certificate.d.ts +38 -0
- package/dist/hub/browser-certificate.js +247 -0
- package/dist/hub/browser-certificate.js.map +1 -0
- package/dist/hub/buttons-model.d.ts +9 -0
- package/dist/hub/buttons-model.js +42 -0
- package/dist/hub/buttons-model.js.map +1 -0
- package/dist/hub/buttons.d.ts +54 -0
- package/dist/hub/buttons.js +346 -0
- package/dist/hub/buttons.js.map +1 -0
- package/dist/hub/catalog.d.ts +74 -0
- package/dist/hub/catalog.js +195 -0
- package/dist/hub/catalog.js.map +1 -0
- package/dist/hub/client.d.ts +69 -0
- package/dist/hub/client.js +300 -0
- package/dist/hub/client.js.map +1 -0
- package/dist/hub/compose/member.d.ts +139 -0
- package/dist/hub/compose/member.js +450 -0
- package/dist/hub/compose/member.js.map +1 -0
- package/dist/hub/compose/server.d.ts +77 -0
- package/dist/hub/compose/server.js +349 -0
- package/dist/hub/compose/server.js.map +1 -0
- package/dist/hub/compose/views.d.ts +12 -0
- package/dist/hub/compose/views.js +4 -0
- package/dist/hub/compose/views.js.map +1 -0
- package/dist/hub/db.d.ts +56 -0
- package/dist/hub/db.js +188 -0
- package/dist/hub/db.js.map +1 -0
- package/dist/hub/directory/config.d.ts +39 -0
- package/dist/hub/directory/config.js +108 -0
- package/dist/hub/directory/config.js.map +1 -0
- package/dist/hub/directory/directory.d.ts +18 -0
- package/dist/hub/directory/directory.js +320 -0
- package/dist/hub/directory/directory.js.map +1 -0
- package/dist/hub/directory/index.d.ts +7 -0
- package/dist/hub/directory/index.js +4 -0
- package/dist/hub/directory/index.js.map +1 -0
- package/dist/hub/directory/profiles.d.ts +41 -0
- package/dist/hub/directory/profiles.js +90 -0
- package/dist/hub/directory/profiles.js.map +1 -0
- package/dist/hub/directory/types.d.ts +71 -0
- package/dist/hub/directory/types.js +14 -0
- package/dist/hub/directory/types.js.map +1 -0
- package/dist/hub/execution/cli-provider.d.ts +23 -0
- package/dist/hub/execution/cli-provider.js +341 -0
- package/dist/hub/execution/cli-provider.js.map +1 -0
- package/dist/hub/execution/index.d.ts +13 -0
- package/dist/hub/execution/index.js +8 -0
- package/dist/hub/execution/index.js.map +1 -0
- package/dist/hub/execution/model-broker.d.ts +24 -0
- package/dist/hub/execution/model-broker.js +208 -0
- package/dist/hub/execution/model-broker.js.map +1 -0
- package/dist/hub/execution/provider-setup.d.ts +11 -0
- package/dist/hub/execution/provider-setup.js +21 -0
- package/dist/hub/execution/provider-setup.js.map +1 -0
- package/dist/hub/execution/sandbox-runner.d.ts +1 -0
- package/dist/hub/execution/sandbox-runner.js +221 -0
- package/dist/hub/execution/sandbox-runner.js.map +1 -0
- package/dist/hub/execution/service.d.ts +136 -0
- package/dist/hub/execution/service.js +459 -0
- package/dist/hub/execution/service.js.map +1 -0
- package/dist/hub/execution/store.d.ts +61 -0
- package/dist/hub/execution/store.js +182 -0
- package/dist/hub/execution/store.js.map +1 -0
- package/dist/hub/execution/views.d.ts +20 -0
- package/dist/hub/execution/views.js +48 -0
- package/dist/hub/execution/views.js.map +1 -0
- package/dist/hub/http/compose.d.ts +20 -0
- package/dist/hub/http/compose.js +518 -0
- package/dist/hub/http/compose.js.map +1 -0
- package/dist/hub/http/core.d.ts +49 -0
- package/dist/hub/http/core.js +124 -0
- package/dist/hub/http/core.js.map +1 -0
- package/dist/hub/http/deps.d.ts +61 -0
- package/dist/hub/http/deps.js +2 -0
- package/dist/hub/http/deps.js.map +1 -0
- package/dist/hub/http/schema.d.ts +14 -0
- package/dist/hub/http/schema.js +80 -0
- package/dist/hub/http/schema.js.map +1 -0
- package/dist/hub/identity.d.ts +32 -0
- package/dist/hub/identity.js +80 -0
- package/dist/hub/identity.js.map +1 -0
- package/dist/hub/init/browser-certificate.d.ts +9 -0
- package/dist/hub/init/browser-certificate.js +78 -0
- package/dist/hub/init/browser-certificate.js.map +1 -0
- package/dist/hub/init/browser-tls.d.ts +18 -0
- package/dist/hub/init/browser-tls.js +62 -0
- package/dist/hub/init/browser-tls.js.map +1 -0
- package/dist/hub/init/cli.d.ts +3 -0
- package/dist/hub/init/cli.js +83 -0
- package/dist/hub/init/cli.js.map +1 -0
- package/dist/hub/init/directory-certificate.d.ts +24 -0
- package/dist/hub/init/directory-certificate.js +222 -0
- package/dist/hub/init/directory-certificate.js.map +1 -0
- package/dist/hub/init/existing-fleet.d.ts +6 -0
- package/dist/hub/init/existing-fleet.js +58 -0
- package/dist/hub/init/existing-fleet.js.map +1 -0
- package/dist/hub/init/handoff.d.ts +8 -0
- package/dist/hub/init/handoff.js +36 -0
- package/dist/hub/init/handoff.js.map +1 -0
- package/dist/hub/init/identity.d.ts +5 -0
- package/dist/hub/init/identity.js +24 -0
- package/dist/hub/init/identity.js.map +1 -0
- package/dist/hub/init/initializer.d.ts +24 -0
- package/dist/hub/init/initializer.js +385 -0
- package/dist/hub/init/initializer.js.map +1 -0
- package/dist/hub/init/inventory.d.ts +17 -0
- package/dist/hub/init/inventory.js +33 -0
- package/dist/hub/init/inventory.js.map +1 -0
- package/dist/hub/init/layout.d.ts +32 -0
- package/dist/hub/init/layout.js +53 -0
- package/dist/hub/init/layout.js.map +1 -0
- package/dist/hub/init/network.d.ts +18 -0
- package/dist/hub/init/network.js +104 -0
- package/dist/hub/init/network.js.map +1 -0
- package/dist/hub/init/plan-digest.d.ts +5 -0
- package/dist/hub/init/plan-digest.js +47 -0
- package/dist/hub/init/plan-digest.js.map +1 -0
- package/dist/hub/init/prompt.d.ts +26 -0
- package/dist/hub/init/prompt.js +110 -0
- package/dist/hub/init/prompt.js.map +1 -0
- package/dist/hub/init/secret-file.d.ts +1 -0
- package/dist/hub/init/secret-file.js +59 -0
- package/dist/hub/init/secret-file.js.map +1 -0
- package/dist/hub/init/text.d.ts +127 -0
- package/dist/hub/init/text.js +247 -0
- package/dist/hub/init/text.js.map +1 -0
- package/dist/hub/init/types.d.ts +114 -0
- package/dist/hub/init/types.js +9 -0
- package/dist/hub/init/types.js.map +1 -0
- package/dist/hub/init/wizard.d.ts +34 -0
- package/dist/hub/init/wizard.js +554 -0
- package/dist/hub/init/wizard.js.map +1 -0
- package/dist/hub/initialization.d.ts +23 -0
- package/dist/hub/initialization.js +28 -0
- package/dist/hub/initialization.js.map +1 -0
- package/dist/hub/member/agent-mode.d.ts +6 -0
- package/dist/hub/member/agent-mode.js +23 -0
- package/dist/hub/member/agent-mode.js.map +1 -0
- package/dist/hub/member/attachments.d.ts +29 -0
- package/dist/hub/member/attachments.js +107 -0
- package/dist/hub/member/attachments.js.map +1 -0
- package/dist/hub/member/exposure-api.d.ts +87 -0
- package/dist/hub/member/exposure-api.js +64 -0
- package/dist/hub/member/exposure-api.js.map +1 -0
- package/dist/hub/member/exposures.d.ts +123 -0
- package/dist/hub/member/exposures.js +282 -0
- package/dist/hub/member/exposures.js.map +1 -0
- package/dist/hub/member/pairing-api.d.ts +85 -0
- package/dist/hub/member/pairing-api.js +385 -0
- package/dist/hub/member/pairing-api.js.map +1 -0
- package/dist/hub/member/quota.d.ts +20 -0
- package/dist/hub/member/quota.js +98 -0
- package/dist/hub/member/quota.js.map +1 -0
- package/dist/hub/member-journal.d.ts +104 -0
- package/dist/hub/member-journal.js +336 -0
- package/dist/hub/member-journal.js.map +1 -0
- package/dist/hub/member-reconciliation.d.ts +14 -0
- package/dist/hub/member-reconciliation.js +97 -0
- package/dist/hub/member-reconciliation.js.map +1 -0
- package/dist/hub/mount.d.ts +39 -0
- package/dist/hub/mount.js +123 -0
- package/dist/hub/mount.js.map +1 -0
- package/dist/hub/pairing-client.d.ts +17 -0
- package/dist/hub/pairing-client.js +108 -0
- package/dist/hub/pairing-client.js.map +1 -0
- package/dist/hub/pairing.d.ts +65 -0
- package/dist/hub/pairing.js +211 -0
- package/dist/hub/pairing.js.map +1 -0
- package/dist/hub/policy.d.ts +63 -0
- package/dist/hub/policy.js +147 -0
- package/dist/hub/policy.js.map +1 -0
- package/dist/hub/preview.d.ts +32 -0
- package/dist/hub/preview.js +64 -0
- package/dist/hub/preview.js.map +1 -0
- package/dist/hub/private-files.d.ts +5 -0
- package/dist/hub/private-files.js +44 -0
- package/dist/hub/private-files.js.map +1 -0
- package/dist/hub/profile.d.ts +59 -0
- package/dist/hub/profile.js +73 -0
- package/dist/hub/profile.js.map +1 -0
- package/dist/hub/protocol.d.ts +779 -0
- package/dist/hub/protocol.js +93 -0
- package/dist/hub/protocol.js.map +1 -0
- package/dist/hub/quota.d.ts +24 -0
- package/dist/hub/quota.js +112 -0
- package/dist/hub/quota.js.map +1 -0
- package/dist/hub/representative.d.ts +141 -0
- package/dist/hub/representative.js +528 -0
- package/dist/hub/representative.js.map +1 -0
- package/dist/hub/retention.d.ts +17 -0
- package/dist/hub/retention.js +45 -0
- package/dist/hub/retention.js.map +1 -0
- package/dist/hub/rooms.d.ts +120 -0
- package/dist/hub/rooms.js +535 -0
- package/dist/hub/rooms.js.map +1 -0
- package/dist/hub/runtime.d.ts +106 -0
- package/dist/hub/runtime.js +298 -0
- package/dist/hub/runtime.js.map +1 -0
- package/dist/hub/server.d.ts +56 -0
- package/dist/hub/server.js +202 -0
- package/dist/hub/server.js.map +1 -0
- package/dist/hub/service-start.d.ts +17 -0
- package/dist/hub/service-start.js +109 -0
- package/dist/hub/service-start.js.map +1 -0
- package/dist/hub/sessions.d.ts +53 -0
- package/dist/hub/sessions.js +196 -0
- package/dist/hub/sessions.js.map +1 -0
- package/dist/hub/socket.d.ts +24 -0
- package/dist/hub/socket.js +79 -0
- package/dist/hub/socket.js.map +1 -0
- package/dist/hub/store.d.ts +77 -0
- package/dist/hub/store.js +88 -0
- package/dist/hub/store.js.map +1 -0
- package/dist/hub/tls.d.ts +31 -0
- package/dist/hub/tls.js +135 -0
- package/dist/hub/tls.js.map +1 -0
- package/dist/hub/types.d.ts +401 -0
- package/dist/hub/types.js +2 -0
- package/dist/hub/types.js.map +1 -0
- package/dist/hub/validation.d.ts +33 -0
- package/dist/hub/validation.js +136 -0
- package/dist/hub/validation.js.map +1 -0
- package/dist/hub/version-floor.d.ts +10 -0
- package/dist/hub/version-floor.js +45 -0
- package/dist/hub/version-floor.js.map +1 -0
- package/dist/hub-browser-certificate-policy.d.ts +31 -0
- package/dist/hub-browser-certificate-policy.js +25 -0
- package/dist/hub-browser-certificate-policy.js.map +1 -0
- package/dist/hub-membership-settings.d.ts +6 -0
- package/dist/hub-membership-settings.js +21 -0
- package/dist/hub-membership-settings.js.map +1 -0
- package/dist/hub-mode.d.ts +15 -0
- package/dist/hub-mode.js +17 -0
- package/dist/hub-mode.js.map +1 -0
- package/dist/hub-pairing-summary.d.ts +48 -0
- package/dist/hub-pairing-summary.js +36 -0
- package/dist/hub-pairing-summary.js.map +1 -0
- package/dist/hub-report-target.d.ts +32 -0
- package/dist/hub-report-target.js +33 -0
- package/dist/hub-report-target.js.map +1 -0
- package/dist/hub-retention-policy.d.ts +14 -0
- package/dist/hub-retention-policy.js +15 -0
- package/dist/hub-retention-policy.js.map +1 -0
- package/dist/instance-config-impact.js +3 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +17 -2
- package/dist/instance-lifecycle.js +58 -8
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-topic-delete.d.ts +77 -0
- package/dist/instance-topic-delete.js +123 -0
- package/dist/instance-topic-delete.js.map +1 -0
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.js +1 -1
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-engine-status.d.ts +11 -0
- package/dist/kiro-engine-status.js +6 -0
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/launchd-service-domain.d.ts +5 -0
- package/dist/launchd-service-domain.js +21 -0
- package/dist/launchd-service-domain.js.map +1 -0
- package/dist/locale.js +125 -3
- package/dist/locale.js.map +1 -1
- package/dist/log-service.d.ts +28 -0
- package/dist/log-service.js +29 -0
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +4 -3
- package/dist/log-steps.js +32 -7
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.d.ts +16 -2
- package/dist/logger.js +346 -66
- package/dist/logger.js.map +1 -1
- package/dist/login-flows.d.ts +15 -7
- package/dist/login-flows.js +29 -3
- package/dist/login-flows.js.map +1 -1
- package/dist/login-manager.js +25 -4
- package/dist/login-manager.js.map +1 -1
- package/dist/ls-rows.js +3 -4
- package/dist/ls-rows.js.map +1 -1
- package/dist/missed-offline.d.ts +25 -0
- package/dist/missed-offline.js +79 -0
- package/dist/missed-offline.js.map +1 -0
- package/dist/native-instance-api.d.ts +0 -1
- package/dist/native-instance-api.js +15 -3
- package/dist/native-instance-api.js.map +1 -1
- package/dist/native-instance-input.d.ts +3 -0
- package/dist/native-instance-input.js +6 -1
- package/dist/native-instance-input.js.map +1 -1
- package/dist/native-instance-registry.d.ts +6 -0
- package/dist/native-instance-registry.js +24 -0
- package/dist/native-instance-registry.js.map +1 -1
- package/dist/native-mcp.d.ts +3 -0
- package/dist/native-mcp.js +15 -2
- package/dist/native-mcp.js.map +1 -1
- package/dist/native-pane-lifecycle.d.ts +8 -0
- package/dist/native-pane-lifecycle.js +13 -4
- package/dist/native-pane-lifecycle.js.map +1 -1
- package/dist/native-pane-manager.js +17 -9
- package/dist/native-pane-manager.js.map +1 -1
- package/dist/needs-you-hub.d.ts +9 -1
- package/dist/needs-you-hub.js +46 -8
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +47 -2
- package/dist/needs-you.js +31 -3
- package/dist/needs-you.js.map +1 -1
- package/dist/office-share-page.js +3 -3
- package/dist/office-share-page.js.map +1 -1
- package/dist/office-share.d.ts +11 -0
- package/dist/office-share.js +14 -0
- package/dist/office-share.js.map +1 -1
- package/dist/office-talk.d.ts +26 -0
- package/dist/office-talk.js +50 -0
- package/dist/office-talk.js.map +1 -0
- package/dist/outbound-handlers.d.ts +14 -0
- package/dist/outbound-handlers.js +49 -6
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +33 -1
- package/dist/outbound-schemas.js +29 -16
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/pane-quota-history.d.ts +9 -0
- package/dist/pane-quota-history.js +67 -0
- package/dist/pane-quota-history.js.map +1 -0
- package/dist/pause-marker.d.ts +1 -1
- package/dist/pause-marker.js +1 -1
- package/dist/pause-marker.js.map +1 -1
- package/dist/platform-general.d.ts +46 -0
- package/dist/platform-general.js +91 -0
- package/dist/platform-general.js.map +1 -0
- package/dist/public-web-gateway.js +7 -0
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +6 -0
- package/dist/public-web-link.js +9 -0
- package/dist/public-web-link.js.map +1 -1
- package/dist/queued-handoffs.d.ts +33 -0
- package/dist/queued-handoffs.js +75 -0
- package/dist/queued-handoffs.js.map +1 -0
- package/dist/quickstart.d.ts +13 -0
- package/dist/quickstart.js +81 -5
- package/dist/quickstart.js.map +1 -1
- package/dist/quota-notice.d.ts +7 -0
- package/dist/quota-notice.js +40 -0
- package/dist/quota-notice.js.map +1 -1
- package/dist/reply-buttons-controller.js +10 -6
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-polls.d.ts +2 -2
- package/dist/reply-polls.js +3 -3
- package/dist/reply-polls.js.map +1 -1
- package/dist/runtime-api.d.ts +2 -0
- package/dist/runtime-api.js +106 -13
- package/dist/runtime-api.js.map +1 -1
- package/dist/runtime-build-info.d.ts +9 -0
- package/dist/runtime-build-info.js +59 -0
- package/dist/runtime-build-info.js.map +1 -0
- package/dist/runtime-bundle.d.ts +6 -1
- package/dist/runtime-bundle.js +17 -9
- package/dist/runtime-bundle.js.map +1 -1
- package/dist/runtime-cli.d.ts +13 -1
- package/dist/runtime-cli.js +173 -19
- package/dist/runtime-cli.js.map +1 -1
- package/dist/runtime-client-store.d.ts +27 -1
- package/dist/runtime-client-store.js +86 -6
- package/dist/runtime-client-store.js.map +1 -1
- package/dist/runtime-client.d.ts +74 -0
- package/dist/runtime-client.js +336 -26
- package/dist/runtime-client.js.map +1 -1
- package/dist/runtime-connection.d.ts +22 -0
- package/dist/runtime-connection.js +93 -0
- package/dist/runtime-connection.js.map +1 -0
- package/dist/runtime-coordinator.d.ts +16 -0
- package/dist/runtime-coordinator.js +287 -62
- package/dist/runtime-coordinator.js.map +1 -1
- package/dist/runtime-credential-profiles.d.ts +78 -0
- package/dist/runtime-credential-profiles.js +280 -0
- package/dist/runtime-credential-profiles.js.map +1 -0
- package/dist/runtime-install.d.ts +50 -0
- package/dist/runtime-install.js +186 -0
- package/dist/runtime-install.js.map +1 -0
- package/dist/runtime-pane-assets.d.ts +1 -1
- package/dist/runtime-pane-assets.js +1 -1
- package/dist/runtime-pane-assets.js.map +1 -1
- package/dist/runtime-pane-boot.d.ts +7 -0
- package/dist/runtime-pane-boot.js +23 -0
- package/dist/runtime-pane-boot.js.map +1 -1
- package/dist/runtime-pane-codex-index.d.ts +10 -1
- package/dist/runtime-pane-codex-index.js +131 -27
- package/dist/runtime-pane-codex-index.js.map +1 -1
- package/dist/runtime-pane-host.d.ts +19 -0
- package/dist/runtime-pane-host.js +50 -7
- package/dist/runtime-pane-host.js.map +1 -1
- package/dist/runtime-pane-link.d.ts +7 -0
- package/dist/runtime-pane-link.js +93 -2
- package/dist/runtime-pane-link.js.map +1 -1
- package/dist/runtime-pane-mcp-relay.d.ts +1 -0
- package/dist/runtime-pane-mcp-relay.js +10 -0
- package/dist/runtime-pane-mcp-relay.js.map +1 -1
- package/dist/runtime-pane-mcp.d.ts +4 -0
- package/dist/runtime-pane-mcp.js +6 -3
- package/dist/runtime-pane-mcp.js.map +1 -1
- package/dist/runtime-pane-native.d.ts +32 -2
- package/dist/runtime-pane-native.js +55 -6
- package/dist/runtime-pane-native.js.map +1 -1
- package/dist/runtime-pane-port.d.ts +5 -0
- package/dist/runtime-pane-port.js +17 -1
- package/dist/runtime-pane-port.js.map +1 -1
- package/dist/runtime-pane-process.d.ts +1 -1
- package/dist/runtime-pane-process.js +11 -2
- package/dist/runtime-pane-process.js.map +1 -1
- package/dist/runtime-pane-protocol.d.ts +11 -1
- package/dist/runtime-pane-protocol.js +27 -5
- package/dist/runtime-pane-protocol.js.map +1 -1
- package/dist/runtime-pane-quota-history.d.ts +6 -0
- package/dist/runtime-pane-quota-history.js +44 -0
- package/dist/runtime-pane-quota-history.js.map +1 -0
- package/dist/runtime-pane-service.d.ts +5 -0
- package/dist/runtime-pane-service.js +47 -12
- package/dist/runtime-pane-service.js.map +1 -1
- package/dist/runtime-pane-transcript.d.ts +5 -0
- package/dist/runtime-pane-transcript.js +66 -5
- package/dist/runtime-pane-transcript.js.map +1 -1
- package/dist/runtime-pane-worker.js +19 -6
- package/dist/runtime-pane-worker.js.map +1 -1
- package/dist/runtime-protocol.d.ts +30 -2
- package/dist/runtime-protocol.js +30 -0
- package/dist/runtime-protocol.js.map +1 -1
- package/dist/runtime-update-activity.d.ts +21 -0
- package/dist/runtime-update-activity.js +51 -0
- package/dist/runtime-update-activity.js.map +1 -0
- package/dist/runtime-update-artifact.d.ts +31 -0
- package/dist/runtime-update-artifact.js +252 -0
- package/dist/runtime-update-artifact.js.map +1 -0
- package/dist/runtime-update-install.d.ts +31 -0
- package/dist/runtime-update-install.js +205 -0
- package/dist/runtime-update-install.js.map +1 -0
- package/dist/runtime-update-journal.d.ts +44 -0
- package/dist/runtime-update-journal.js +121 -0
- package/dist/runtime-update-journal.js.map +1 -0
- package/dist/runtime-update-lock.d.ts +48 -0
- package/dist/runtime-update-lock.js +217 -0
- package/dist/runtime-update-lock.js.map +1 -0
- package/dist/runtime-update-owners.d.ts +29 -0
- package/dist/runtime-update-owners.js +240 -0
- package/dist/runtime-update-owners.js.map +1 -0
- package/dist/runtime-update-protocol.d.ts +15 -0
- package/dist/runtime-update-protocol.js +13 -0
- package/dist/runtime-update-protocol.js.map +1 -0
- package/dist/runtime-windows-bridge.d.ts +2 -1
- package/dist/runtime-windows-bridge.js +11 -1
- package/dist/runtime-windows-bridge.js.map +1 -1
- package/dist/scheduler/db.d.ts +2 -1
- package/dist/scheduler/db.js +23 -9
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/task-board-text.js +1 -1
- package/dist/scheduler/task-board-text.js.map +1 -1
- package/dist/scheduler/task-board.d.ts +13 -0
- package/dist/scheduler/task-board.js +28 -3
- package/dist/scheduler/task-board.js.map +1 -1
- package/dist/service-drain.d.ts +19 -0
- package/dist/service-drain.js +64 -0
- package/dist/service-drain.js.map +1 -0
- package/dist/service-installer.d.ts +7 -2
- package/dist/service-installer.js +13 -10
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.d.ts +20 -0
- package/dist/settings-api.js +414 -4
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.d.ts +6 -0
- package/dist/settings-baseline.js +3 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.js +29 -6
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.d.ts +13 -0
- package/dist/settings-effect.js +98 -1
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +3 -0
- package/dist/settings-http-confirmation.js +28 -1
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +27 -0
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/setup-wizard.js +6 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/task-board-tool.d.ts +13 -1
- package/dist/task-board-tool.js +104 -4
- package/dist/task-board-tool.js.map +1 -1
- package/dist/task-board-waker.d.ts +6 -0
- package/dist/task-board-waker.js +4 -0
- package/dist/task-board-waker.js.map +1 -1
- package/dist/tmux-binary.d.ts +59 -0
- package/dist/tmux-binary.js +200 -0
- package/dist/tmux-binary.js.map +1 -0
- package/dist/tmux-control.js +4 -4
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.js +32 -1
- package/dist/tmux-exec-helper.js.map +1 -1
- package/dist/tmux-manager.d.ts +1 -1
- package/dist/tmux-manager.js +45 -36
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +4 -3
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.d.ts +5 -2
- package/dist/tool-permissions.js +6 -5
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.d.ts +2 -0
- package/dist/tool-progress.js +19 -3
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-commands.js +10 -5
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.d.ts +20 -0
- package/dist/transcript-monitor.js +47 -3
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-needles.d.ts +7 -0
- package/dist/transcript-needles.js +9 -1
- package/dist/transcript-needles.js.map +1 -1
- package/dist/transcript-records.d.ts +1 -1
- package/dist/transcript-records.js +2 -1
- package/dist/transcript-records.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/ui/account-identity.js +27 -0
- package/dist/ui/accounts-view.js +214 -0
- package/dist/ui/agent-runtime-settings.js +68 -0
- package/dist/ui/agent-runtime.js +20 -2
- package/dist/ui/backend-signin.js +39 -21
- package/dist/ui/chat-ambient.js +1 -1
- package/dist/ui/chat-md-strings.js +3 -0
- package/dist/ui/chat-render.js +3 -670
- package/dist/ui/chat-store.js +1 -1
- package/dist/ui/chat-strings.js +3 -333
- package/dist/ui/chat-thread.js +3 -919
- package/dist/ui/chat-time.js +3 -80
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/credential-profile-select.js +54 -0
- package/dist/ui/fleet-office-dialogue.d.ts +30 -0
- package/dist/ui/fleet-office-dialogue.js +382 -0
- package/dist/ui/fleet-office-pack.d.ts +9 -0
- package/dist/ui/fleet-office-pack.js +76 -4
- package/dist/ui/fleet-office-skin.js +23 -5
- package/dist/ui/fleet-office-store.js +5 -0
- package/dist/ui/fleet-office.js +173 -6
- package/dist/ui/fleet-task-card.js +10 -6
- package/dist/ui/fleet-task-common.js +12 -2
- package/dist/ui/fleet-task-menu.js +188 -0
- package/dist/ui/fleet-task-stats.js +124 -0
- package/dist/ui/fleet-task-view.js +340 -0
- package/dist/ui/fleet-tasks.js +131 -43
- package/dist/ui/fleet-usage.js +90 -27
- package/dist/ui/html-attachment.js +3 -40
- package/dist/ui/hub-agent-copy.js +23 -0
- package/dist/ui/hub-button-actions.js +65 -0
- package/dist/ui/hub-chat-store.js +158 -0
- package/dist/ui/hub-chat-strings.js +77 -0
- package/dist/ui/hub-client.js +329 -0
- package/dist/ui/hub-owner-strings.js +51 -0
- package/dist/ui/hub-provider-guidance.js +31 -0
- package/dist/ui/hub-quota.js +85 -0
- package/dist/ui/hub-strings.js +162 -0
- package/dist/ui/hub-switcher.js +27 -0
- package/dist/ui/native-instance-settings.js +5 -8
- package/dist/ui/native-pane-recovery.js +1 -1
- package/dist/ui/office-share-page.js +4 -2
- package/dist/ui/panel-chat.js +36 -49
- package/dist/ui/panel-details.js +1 -1
- package/dist/ui/panel-fleet.js +82 -12
- package/dist/ui/panel-hub.js +619 -0
- package/dist/ui/panel-log.js +2 -2
- package/dist/ui/panel-needs.js +24 -8
- package/dist/ui/panel-runtimes.js +239 -45
- package/dist/ui/panel-settings.js +266 -192
- package/dist/ui/panel-windows-cli.js +88 -42
- package/dist/ui/preview-pages.js +1 -1
- package/dist/ui/preview-panel.js +92 -6
- package/dist/ui/preview-versions.js +1 -1
- package/dist/ui/preview.js +3 -476
- package/dist/ui/runtime-commands.d.ts +4 -0
- package/dist/ui/runtime-commands.js +59 -0
- package/dist/ui/search-dialog.js +2 -0
- package/dist/ui/settings-access-strings.js +42 -0
- package/dist/ui/settings-agent-filters.js +94 -0
- package/dist/ui/settings-appearance.js +122 -23
- package/dist/ui/settings-build-version.js +35 -0
- package/dist/ui/settings-codex-copy.js +19 -0
- package/dist/ui/settings-devices.js +253 -0
- package/dist/ui/settings-dialogs.js +33 -12
- package/dist/ui/settings-guests.js +25 -11
- package/dist/ui/settings-hub-browser-certificate.js +74 -0
- package/dist/ui/settings-hub-membership.js +72 -0
- package/dist/ui/settings-hub-retention.js +52 -0
- package/dist/ui/settings-hub.js +196 -0
- package/dist/ui/settings-layout.js +242 -0
- package/dist/ui/settings-model.js +24 -2
- package/dist/ui/settings-outside.js +104 -38
- package/dist/ui/settings-registry.js +9 -4
- package/dist/ui/settings-shared-strings.js +143 -0
- package/dist/ui/settings-shared.js +345 -0
- package/dist/ui/settings-shortcuts.js +65 -0
- package/dist/ui/settings-strings.js +89 -32
- package/dist/ui/settings-web-authority.js +17 -11
- package/dist/ui/shared/accounts.css +15 -0
- package/dist/ui/shared/app-i18n.js +2 -2
- package/dist/ui/shared/app-needs.js +1 -1
- package/dist/ui/shared/app-route.js +6 -1
- package/dist/ui/shared/app-session.js +6 -2
- package/dist/ui/shared/app-shell.js +81 -15
- package/dist/ui/shared/app.css +1114 -13
- package/dist/ui/shared/app.js +12 -3
- package/dist/ui/shared/chat-composer.js +68 -0
- package/dist/ui/shared/chat-md-strings.js +9 -0
- package/dist/ui/shared/chat-render.js +682 -0
- package/dist/ui/shared/chat-strings.js +333 -0
- package/dist/ui/shared/chat-thread.js +969 -0
- package/dist/ui/shared/chat-time.js +80 -0
- package/dist/ui/shared/header-tools.js +3 -5
- package/dist/ui/shared/html-attachment.js +42 -0
- package/dist/ui/shared/hub-chat.css +85 -0
- package/dist/ui/shared/hub-owner.css +33 -0
- package/dist/ui/shared/hub-quota.css +8 -0
- package/dist/ui/shared/hub.css +71 -0
- package/dist/ui/shared/instance-nav.js +3 -2
- package/dist/ui/shared/machine-name.js +13 -0
- package/dist/ui/shared/page-head.js +8 -0
- package/dist/ui/shared/panel-view.js +77 -4
- package/dist/ui/shared/preview.js +476 -0
- package/dist/ui/shared/runtime-install.css +26 -0
- package/dist/ui/shared/settings-width.js +31 -0
- package/dist/ui/shared/side-rail.js +15 -0
- package/dist/ui/shared/signin.js +172 -0
- package/dist/ui/shared/task-board.css +95 -0
- package/dist/ui/shared/tokens.css +1 -0
- package/dist/ui/shared/ui-dialog.js +2 -2
- package/dist/ui/shared/ui-menu.js +3 -3
- package/dist/ui/shared/usage-dialog.js +18 -1
- package/dist/ui/shared/view-history.css +17 -0
- package/dist/ui/shared/view-history.js +438 -0
- package/dist/ui/shared/view-strings.js +16 -0
- package/dist/ui/shared/workspace.css +20 -0
- package/dist/ui/signin.html +21 -0
- package/dist/ui/windows-cli-catalog.js +41 -12
- package/dist/ui/workspace-panel.js +189 -0
- package/dist/ui/workspace-strings.js +35 -0
- package/dist/unattended-install.d.ts +11 -2
- package/dist/unattended-install.js +41 -6
- package/dist/unattended-install.js.map +1 -1
- package/dist/usage/capacity.d.ts +69 -0
- package/dist/usage/capacity.js +119 -0
- package/dist/usage/capacity.js.map +1 -0
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +3 -0
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/profile-timeline.d.ts +16 -0
- package/dist/usage/profile-timeline.js +58 -0
- package/dist/usage/profile-timeline.js.map +1 -0
- package/dist/usage/providers.js +2 -1
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/quota-history.d.ts +43 -0
- package/dist/usage/quota-history.js +168 -0
- package/dist/usage/quota-history.js.map +1 -0
- package/dist/usage/usage-api.d.ts +31 -0
- package/dist/usage/usage-api.js +80 -1
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.d.ts +25 -1
- package/dist/usage-report.js +55 -4
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.d.ts +6 -1
- package/dist/usage-rollup.js +16 -4
- package/dist/usage-rollup.js.map +1 -1
- package/dist/view-api.d.ts +16 -0
- package/dist/view-api.js +105 -23
- package/dist/view-api.js.map +1 -1
- package/dist/view-history.d.ts +84 -0
- package/dist/view-history.js +116 -0
- package/dist/view-history.js.map +1 -0
- package/dist/web-api.d.ts +49 -2
- package/dist/web-api.js +279 -8
- package/dist/web-api.js.map +1 -1
- package/dist/web-backend-login.d.ts +23 -1
- package/dist/web-backend-login.js +11 -17
- package/dist/web-backend-login.js.map +1 -1
- package/dist/web-device-login.d.ts +153 -0
- package/dist/web-device-login.js +278 -0
- package/dist/web-device-login.js.map +1 -0
- package/dist/web-office-skins.d.ts +9 -0
- package/dist/web-office-skins.js +16 -1
- package/dist/web-office-skins.js.map +1 -1
- package/dist/web-session-authorization.d.ts +13 -2
- package/dist/web-session-authorization.js +10 -3
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.d.ts +35 -0
- package/dist/web-session.js +7 -0
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +4 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-shell-routes.d.ts +6 -0
- package/dist/web-shell-routes.js +7 -0
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-terminal.d.ts +4 -30
- package/dist/web-terminal.js +9 -6
- package/dist/web-terminal.js.map +1 -1
- package/dist/windows-agents.d.ts +4 -1
- package/dist/windows-agents.js +14 -10
- package/dist/windows-agents.js.map +1 -1
- package/dist/windows-cli-api.d.ts +12 -1
- package/dist/windows-cli-api.js +29 -2
- package/dist/windows-cli-api.js.map +1 -1
- package/dist/windows-cli-providers.d.ts +0 -9
- package/dist/windows-cli-providers.js +4 -9
- package/dist/windows-cli-providers.js.map +1 -1
- package/dist/windows-cli-worker.d.ts +25 -0
- package/dist/windows-cli-worker.js +98 -7
- package/dist/windows-cli-worker.js.map +1 -1
- package/dist/windows-cli.d.ts +11 -0
- package/dist/windows-cli.js +17 -3
- package/dist/windows-cli.js.map +1 -1
- package/dist/yaml-shared-nodes.js +8 -3
- package/dist/yaml-shared-nodes.js.map +1 -1
- package/launcher/agend-install.cjs +8 -1
- package/launcher/launchd-session-type.cjs +14 -0
- package/launcher/postinstall.cjs +27 -2
- package/launcher/private-home.cjs +1 -1
- package/launcher/tmux-bundle.cjs +247 -0
- package/package.json +3 -2
- package/templates/launchd.plist.ejs +3 -1
- package/templates/runtime-install/install.ps1 +270 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgEnD Hub P1, slice 3: the pieces every S3 service shares — the clock, one atomic unit with its audit, the person
|
|
3
|
+
* rows and the fresh directory check (with its concurrency bound). No I/O on import.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { HubProtocolError } from "../validation.js";
|
|
7
|
+
import { personKeyString } from "../identity.js";
|
|
8
|
+
/** At most this many directory checks in flight per person, and in all; more is backpressure (429), never a cached allow. */
|
|
9
|
+
export const DIRECTORY_PER_PERSON = 4;
|
|
10
|
+
export const DIRECTORY_TOTAL = 32;
|
|
11
|
+
export class HubCore {
|
|
12
|
+
deps;
|
|
13
|
+
sql;
|
|
14
|
+
inflight = new Map();
|
|
15
|
+
total = 0;
|
|
16
|
+
constructor(deps, sql) {
|
|
17
|
+
this.deps = deps;
|
|
18
|
+
this.sql = sql;
|
|
19
|
+
}
|
|
20
|
+
now() { return this.deps.now?.() ?? Date.now(); }
|
|
21
|
+
/** Refuses once the server is fenced (and before every write: a stale continuation never commits). */
|
|
22
|
+
live() { try {
|
|
23
|
+
return this.deps.current().serverEnabled() === true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
} }
|
|
28
|
+
check() { if (!this.live())
|
|
29
|
+
throw new HubProtocolError("unavailable"); }
|
|
30
|
+
/** One synchronous unit of work on the Hub DB; a promise returned from `work` is refused. */
|
|
31
|
+
atomic(work) {
|
|
32
|
+
this.check();
|
|
33
|
+
return this.deps.uow.atomic((tx) => {
|
|
34
|
+
this.check();
|
|
35
|
+
const out = work(this.sql(tx), tx);
|
|
36
|
+
if (out && typeof out.then === "function")
|
|
37
|
+
throw new HubProtocolError("invalid");
|
|
38
|
+
return out;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** Audit inside the caller's transaction: a failed append aborts the whole unit (hub.md §4). */
|
|
42
|
+
audit(tx, event) {
|
|
43
|
+
const { at, ...rest } = event;
|
|
44
|
+
let policyVersion = 0;
|
|
45
|
+
try {
|
|
46
|
+
policyVersion = this.deps.store.read().revocationVersion;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
throw new HubProtocolError("uncertain");
|
|
50
|
+
}
|
|
51
|
+
this.deps.audit.append(tx, { ...rest, id: randomUUID(), sequence: 0, at: at ?? this.now(), policyVersion });
|
|
52
|
+
}
|
|
53
|
+
revocationVersion() {
|
|
54
|
+
try {
|
|
55
|
+
return this.deps.store.read().revocationVersion;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new HubProtocolError("uncertain");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A fresh directory eligibility check (no allow-cache). Ineligible or unreachable is denied; the person's row records
|
|
63
|
+
* what was seen. Bounded per person and in all — over the bound is "backpressure".
|
|
64
|
+
*/
|
|
65
|
+
async eligible(person) { return (await this.current(person)) !== null; }
|
|
66
|
+
/**
|
|
67
|
+
* The person as the directory has them now (its current login and name), or null when they are not eligible. The
|
|
68
|
+
* person's row takes the current login label, so a rename never leaves an old label pointing at them.
|
|
69
|
+
*/
|
|
70
|
+
async current(person) {
|
|
71
|
+
const id = personKeyString(person);
|
|
72
|
+
const mine = this.inflight.get(id) ?? 0;
|
|
73
|
+
if (mine >= DIRECTORY_PER_PERSON || this.total >= DIRECTORY_TOTAL)
|
|
74
|
+
throw new HubProtocolError("backpressure");
|
|
75
|
+
this.inflight.set(id, mine + 1);
|
|
76
|
+
this.total++;
|
|
77
|
+
try {
|
|
78
|
+
const r = await this.deps.directory.checkEligibility(person);
|
|
79
|
+
const ok = r.eligible && personKeyString(r.person.key) === id;
|
|
80
|
+
this.check();
|
|
81
|
+
this.atomic((db) => {
|
|
82
|
+
db.prepare("UPDATE hub_people SET status=?, last_checked_at=? WHERE person=?")
|
|
83
|
+
.run(ok ? "active" : r.eligible ? "unknown" : r.reason === "unavailable" ? "unknown" : "disabled", this.now(), id);
|
|
84
|
+
if (ok && r.eligible && typeof r.person.login === "string" && r.person.login)
|
|
85
|
+
db.prepare("UPDATE hub_people SET login_label=? WHERE person=?").run(r.person.login.slice(0, 256), id);
|
|
86
|
+
if (!ok && !(!r.eligible && r.reason === "unavailable"))
|
|
87
|
+
db.prepare("UPDATE hub_sessions SET state='ended' WHERE person=? AND state='active'").run(id);
|
|
88
|
+
});
|
|
89
|
+
return ok && r.eligible ? { login: r.person.login, ...(r.person.displayName ? { displayName: r.person.displayName } : {}) } : null;
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
const n = (this.inflight.get(id) ?? 1) - 1;
|
|
93
|
+
if (n > 0)
|
|
94
|
+
this.inflight.set(id, n);
|
|
95
|
+
else
|
|
96
|
+
this.inflight.delete(id);
|
|
97
|
+
this.total--;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export const personFromRow = (row) => ({ realm: row.realm, objectId: row.object_id });
|
|
102
|
+
export function personFromString(id) {
|
|
103
|
+
const at = id.indexOf("/");
|
|
104
|
+
return { realm: id.slice(0, at), objectId: id.slice(at + 1) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A login label → the one Hub person it names NOW: exactly one row carries it (a shared or unknown label is refused),
|
|
108
|
+
* and the directory's current login for that person is still that label (a rename — and a colleague later given the old
|
|
109
|
+
* login — never redirects a grant or a pairing to the wrong person). Null otherwise.
|
|
110
|
+
*/
|
|
111
|
+
export async function personByLogin(core, login) {
|
|
112
|
+
const label = login.trim();
|
|
113
|
+
if (!label)
|
|
114
|
+
return null;
|
|
115
|
+
const id = core.atomic((db) => {
|
|
116
|
+
const rows = db.prepare("SELECT person FROM hub_people WHERE login_label=? COLLATE NOCASE").all(label);
|
|
117
|
+
return rows.length === 1 ? rows[0].person : null;
|
|
118
|
+
});
|
|
119
|
+
if (!id)
|
|
120
|
+
return null;
|
|
121
|
+
const person = personFromString(id), now = await core.current(person);
|
|
122
|
+
return now && now.login.toLowerCase() === label.toLowerCase() ? person : null;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/hub/http/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgEnD Hub P1, slice 3 (server side): what S5's server factory hands `createHubHttp` (docs/design/hub-composition.md §5
|
|
3
|
+
* step 5, agreed with S5 on cid-hub-s3b-deps). Types only — importing this file creates no state.
|
|
4
|
+
*/
|
|
5
|
+
import type Database from "better-sqlite3";
|
|
6
|
+
import type { HubAskerEnvelope, HubAuditSink, HubDirectory, HubMode, HubServerTransport, HubTx, HubUnitOfWork, PersonKey } from "../types.js";
|
|
7
|
+
import type { HubPairingService } from "../pairing.js";
|
|
8
|
+
import type { HubTransportStore } from "../store.js";
|
|
9
|
+
import type { HubAnswerButtons } from "../types.js";
|
|
10
|
+
import type { HubPollBallot } from "../types.js";
|
|
11
|
+
/** The `hub` section the sealed manifest covers — frozen, validated, never re-read from a request. */
|
|
12
|
+
export interface HubHttpConfig {
|
|
13
|
+
readonly hubId: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly webOrigin: string;
|
|
16
|
+
readonly administrator: PersonKey;
|
|
17
|
+
}
|
|
18
|
+
/** S1's `signAsker` over `hub/keys/issuer-key.pem`; S3 never opens a key file. */
|
|
19
|
+
export interface HubIssuer {
|
|
20
|
+
readonly keyId: string;
|
|
21
|
+
sign(envelope: Omit<HubAskerEnvelope, "signature">): HubAskerEnvelope;
|
|
22
|
+
}
|
|
23
|
+
/** Encrypted question/answer payloads (S5, under content.key). One payload per record; S5 chooses the ref. */
|
|
24
|
+
export interface HubContentStore {
|
|
25
|
+
put(tx: HubTx, payload: {
|
|
26
|
+
question?: string;
|
|
27
|
+
answer?: string;
|
|
28
|
+
buttons?: HubAnswerButtons;
|
|
29
|
+
pollBallot?: HubPollBallot;
|
|
30
|
+
}): string;
|
|
31
|
+
/** S3's own room projection only, after its audience check. Undefined: retention removed it (shown as expired). */
|
|
32
|
+
get(ref: string): {
|
|
33
|
+
question?: string;
|
|
34
|
+
answer?: string;
|
|
35
|
+
buttons?: HubAnswerButtons;
|
|
36
|
+
pollBallot?: HubPollBallot;
|
|
37
|
+
} | undefined;
|
|
38
|
+
}
|
|
39
|
+
export interface HubHttpDeps {
|
|
40
|
+
uow: HubUnitOfWork;
|
|
41
|
+
audit: HubAuditSink;
|
|
42
|
+
directory: HubDirectory;
|
|
43
|
+
pairing: HubPairingService;
|
|
44
|
+
store: HubTransportStore;
|
|
45
|
+
config: HubHttpConfig;
|
|
46
|
+
preview?: Readonly<import("../preview.js").HubPreviewView>;
|
|
47
|
+
issuer: HubIssuer;
|
|
48
|
+
/** Re-read on every use: null before HubServer exists and after fence/close — then work is unavailable, never queued. */
|
|
49
|
+
transport(): Pick<HubServerTransport, "send"> | null;
|
|
50
|
+
content: HubContentStore;
|
|
51
|
+
/** attachments-v1 files (absent: this Hub stores none, and offers no upload). */
|
|
52
|
+
attachments?: import("../attachments/store.js").HubAttachmentStore;
|
|
53
|
+
/** The server's mode (S5): `serverEnabled()` false once fenced — every request and continuation refuses from then on. */
|
|
54
|
+
current(): HubMode;
|
|
55
|
+
now?: () => number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* S5's `hubTxDatabase(tx)` (db.ts): the DB behind a tx, valid only while that tx's `atomic` callback runs. Passed in
|
|
59
|
+
* until S5's db.ts lands, then imported by compose.ts.
|
|
60
|
+
*/
|
|
61
|
+
export type HubTxDatabase = (tx: HubTx) => Database.Database;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps.js","sourceRoot":"","sources":["../../../src/hub/http/deps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgEnD Hub P1, slice 3: S3's own tables in the Hub server DB (`hub/hub.sqlite`), as S5 `HubMigration`s (component
|
|
3
|
+
* "s3-http"). Nothing migrates on import; S5 runs `up` inside its immediate migration transaction.
|
|
4
|
+
*
|
|
5
|
+
* No question or answer text lives here: rooms keep S5 content refs (encrypted under content.key). Session and CSRF
|
|
6
|
+
* secrets are kept only as SHA-256 digests.
|
|
7
|
+
*/
|
|
8
|
+
import type Database from "better-sqlite3";
|
|
9
|
+
export interface HubHttpMigration {
|
|
10
|
+
readonly component: string;
|
|
11
|
+
readonly version: number;
|
|
12
|
+
up(db: Database.Database): void;
|
|
13
|
+
}
|
|
14
|
+
export declare const HUB_HTTP_MIGRATIONS: readonly HubHttpMigration[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { HUB_BUTTONS_MIGRATION } from "../buttons.js";
|
|
2
|
+
const V1 = `
|
|
3
|
+
CREATE TABLE hub_people (
|
|
4
|
+
person TEXT PRIMARY KEY, -- personKeyString(key)
|
|
5
|
+
realm TEXT NOT NULL, object_id TEXT NOT NULL,
|
|
6
|
+
display_name TEXT NOT NULL, login_label TEXT NOT NULL,
|
|
7
|
+
status TEXT NOT NULL CHECK (status IN ('active','disabled','unknown')),
|
|
8
|
+
last_checked_at INTEGER NOT NULL
|
|
9
|
+
);
|
|
10
|
+
CREATE INDEX hub_people_login ON hub_people(login_label);
|
|
11
|
+
CREATE TABLE hub_sessions (
|
|
12
|
+
token_hash TEXT PRIMARY KEY,
|
|
13
|
+
id TEXT NOT NULL UNIQUE,
|
|
14
|
+
person TEXT NOT NULL REFERENCES hub_people(person),
|
|
15
|
+
created_at INTEGER NOT NULL, seen_at INTEGER NOT NULL, expires_at INTEGER NOT NULL,
|
|
16
|
+
state TEXT NOT NULL CHECK (state IN ('active','ended'))
|
|
17
|
+
);
|
|
18
|
+
CREATE INDEX hub_sessions_person ON hub_sessions(person, state);
|
|
19
|
+
CREATE TABLE hub_catalog_cursor (
|
|
20
|
+
fleet_id TEXT PRIMARY KEY, revision INTEGER NOT NULL, digest TEXT NOT NULL, at INTEGER NOT NULL
|
|
21
|
+
);
|
|
22
|
+
CREATE TABLE hub_exposures (
|
|
23
|
+
id TEXT PRIMARY KEY, fleet_id TEXT NOT NULL, owner TEXT NOT NULL,
|
|
24
|
+
display_name TEXT NOT NULL, revision INTEGER NOT NULL,
|
|
25
|
+
state TEXT NOT NULL CHECK (state IN ('published','withdrawn','frozen')),
|
|
26
|
+
data_view_id TEXT NOT NULL, allowed_tools TEXT NOT NULL, policy_digest TEXT NOT NULL,
|
|
27
|
+
frozen_through INTEGER NOT NULL DEFAULT -1, -- a Hub-side freeze holds every revision up to this one
|
|
28
|
+
updated_at INTEGER NOT NULL
|
|
29
|
+
);
|
|
30
|
+
CREATE INDEX hub_exposures_owner ON hub_exposures(owner);
|
|
31
|
+
CREATE INDEX hub_exposures_fleet ON hub_exposures(fleet_id);
|
|
32
|
+
CREATE TABLE hub_grants (
|
|
33
|
+
id TEXT PRIMARY KEY, revision INTEGER NOT NULL, owner TEXT NOT NULL,
|
|
34
|
+
exposure_id TEXT NOT NULL REFERENCES hub_exposures(id), exposure_revision INTEGER NOT NULL,
|
|
35
|
+
approved_by TEXT NOT NULL, approved_at INTEGER NOT NULL, subject TEXT NOT NULL,
|
|
36
|
+
permissions TEXT NOT NULL, starts_at INTEGER NOT NULL, expires_at INTEGER NOT NULL,
|
|
37
|
+
state TEXT NOT NULL CHECK (state IN ('active','revoked'))
|
|
38
|
+
);
|
|
39
|
+
CREATE INDEX hub_grants_subject ON hub_grants(subject, state);
|
|
40
|
+
CREATE INDEX hub_grants_exposure ON hub_grants(exposure_id, state);
|
|
41
|
+
CREATE TABLE hub_rooms (
|
|
42
|
+
id TEXT PRIMARY KEY, asker TEXT NOT NULL, exposure_id TEXT NOT NULL, owner_at_creation TEXT NOT NULL,
|
|
43
|
+
grant_id TEXT NOT NULL REFERENCES hub_grants(id),
|
|
44
|
+
state TEXT NOT NULL CHECK (state IN ('active','held','closed')), created_at INTEGER NOT NULL,
|
|
45
|
+
UNIQUE (asker, exposure_id, grant_id)
|
|
46
|
+
);
|
|
47
|
+
CREATE TABLE hub_messages (
|
|
48
|
+
id TEXT PRIMARY KEY, room_id TEXT NOT NULL REFERENCES hub_rooms(id),
|
|
49
|
+
idempotency_key TEXT NOT NULL, sequence INTEGER NOT NULL,
|
|
50
|
+
fleet_id TEXT NOT NULL, exposure_id TEXT NOT NULL, exposure_revision INTEGER NOT NULL,
|
|
51
|
+
grant_id TEXT NOT NULL, grant_revision INTEGER NOT NULL, asker TEXT NOT NULL, owner TEXT NOT NULL,
|
|
52
|
+
content_digest TEXT NOT NULL, question_ref TEXT NOT NULL,
|
|
53
|
+
stage TEXT NOT NULL, member_sequence INTEGER NOT NULL DEFAULT 0, reason_code TEXT, stage_at INTEGER NOT NULL,
|
|
54
|
+
sent_epoch INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
answer_id TEXT, answer_digest TEXT, answer_ref TEXT,
|
|
56
|
+
created_at INTEGER NOT NULL, expires_at INTEGER NOT NULL,
|
|
57
|
+
UNIQUE (room_id, idempotency_key), UNIQUE (room_id, sequence)
|
|
58
|
+
);
|
|
59
|
+
CREATE INDEX hub_messages_fleet ON hub_messages(fleet_id, stage);
|
|
60
|
+
CREATE TABLE hub_receipts (
|
|
61
|
+
fleet_id TEXT NOT NULL, sequence INTEGER NOT NULL, message_id TEXT NOT NULL, content_digest TEXT NOT NULL,
|
|
62
|
+
stage TEXT NOT NULL, at INTEGER NOT NULL, member_delivery_id TEXT, reason_code TEXT,
|
|
63
|
+
PRIMARY KEY (fleet_id, sequence)
|
|
64
|
+
);
|
|
65
|
+
CREATE TABLE hub_leases (
|
|
66
|
+
decision_id TEXT PRIMARY KEY, fleet_id TEXT NOT NULL, link_epoch INTEGER NOT NULL,
|
|
67
|
+
message_id TEXT NOT NULL, operation_id TEXT NOT NULL, phase TEXT NOT NULL, operation_digest TEXT NOT NULL,
|
|
68
|
+
exposure_revision INTEGER NOT NULL, revocation_version INTEGER NOT NULL, expires_at INTEGER NOT NULL,
|
|
69
|
+
consumed INTEGER NOT NULL DEFAULT 0
|
|
70
|
+
);
|
|
71
|
+
CREATE INDEX hub_leases_message ON hub_leases(message_id);
|
|
72
|
+
`;
|
|
73
|
+
export const HUB_HTTP_MIGRATIONS = Object.freeze([
|
|
74
|
+
Object.freeze({ component: "s3-http", version: 1, up: (db) => { db.exec(V1); } }),
|
|
75
|
+
Object.freeze({ component: "s3-quota", version: 1, up: (db) => {
|
|
76
|
+
db.exec("CREATE TABLE hub_quota_preferences(exposure_id TEXT PRIMARY KEY REFERENCES hub_exposures(id), visible INTEGER NOT NULL CHECK(visible IN (0,1)))");
|
|
77
|
+
} }),
|
|
78
|
+
HUB_BUTTONS_MIGRATION,
|
|
79
|
+
]);
|
|
80
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/hub/http/schema.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAItD,MAAM,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsEV,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAgC,MAAM,CAAC,MAAM,CAAC;IAC5E,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,SAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAqB,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7G,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,UAAmB,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAqB,EAAE,EAAE;YACxF,EAAE,CAAC,IAAI,CAAC,iJAAiJ,CAAC,CAAC;QAC7J,CAAC,EAAE,CAAC;IACJ,qBAAqB;CACtB,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type KeyObject } from "node:crypto";
|
|
2
|
+
import type { HubAskerEnvelope, HubAttachmentRef, HubAuthorizationRequest, HubAuthorizationLease, PersonKey } from "./types.js";
|
|
3
|
+
export declare const sha256: (input: string | Buffer) => string;
|
|
4
|
+
/** The canonical digest of an attachments-v1 file list, in its order. */
|
|
5
|
+
export declare function attachmentsDigest(refs: readonly HubAttachmentRef[]): string;
|
|
6
|
+
/** A message's contentDigest. With nothing but text it is sha256(text), as before. With files (D) and/or reply buttons
|
|
7
|
+
* (F, its own canonical digest) it also binds them, so the asker signature, receipts and the release lease cover them
|
|
8
|
+
* with no new envelope or lease field. */
|
|
9
|
+
export declare function messageContentDigest(kind: "question" | "answer", text: string, extras?: {
|
|
10
|
+
attachments?: readonly HubAttachmentRef[];
|
|
11
|
+
buttonsDigest?: string;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function personKeyString(input: PersonKey): string;
|
|
14
|
+
export declare function signAsker(input: Omit<HubAskerEnvelope, "signature">, key: KeyObject): HubAskerEnvelope;
|
|
15
|
+
export interface HubIdentityBinding {
|
|
16
|
+
hubId: string;
|
|
17
|
+
issuerKeyId: string;
|
|
18
|
+
issuerPublicKey: KeyObject;
|
|
19
|
+
fleetId: string;
|
|
20
|
+
owner: PersonKey;
|
|
21
|
+
revocationVersion: number;
|
|
22
|
+
now: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function verifyAsker(input: unknown, text: string, binding: HubIdentityBinding, attachments?: readonly HubAttachmentRef[]): HubAskerEnvelope;
|
|
25
|
+
export declare function operationDigest(input: HubAuthorizationRequest): string;
|
|
26
|
+
export declare function verifyLease(input: HubAuthorizationLease, request: HubAuthorizationRequest, expected: {
|
|
27
|
+
linkEpoch: number;
|
|
28
|
+
revocationVersion: number;
|
|
29
|
+
now: number;
|
|
30
|
+
}): HubAuthorizationLease;
|
|
31
|
+
export declare function canonicalArguments(input: unknown): string;
|
|
32
|
+
export declare function issuerKeyId(key: KeyObject): string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createHash, createPublicKey, sign, verify } from "node:crypto";
|
|
2
|
+
import { person, validated, parseStrictJson, HubProtocolError } from "./validation.js";
|
|
3
|
+
import { leaseSchema, validateAsker, validateAuthorization } from "./protocol.js";
|
|
4
|
+
export const sha256 = (input) => createHash("sha256").update(input).digest("hex");
|
|
5
|
+
/** The canonical digest of an attachments-v1 file list, in its order. */
|
|
6
|
+
export function attachmentsDigest(refs) {
|
|
7
|
+
return sha256(JSON.stringify(refs.map(r => [r.id, r.name, r.size, r.mime, r.sha256])));
|
|
8
|
+
}
|
|
9
|
+
/** A message's contentDigest. With nothing but text it is sha256(text), as before. With files (D) and/or reply buttons
|
|
10
|
+
* (F, its own canonical digest) it also binds them, so the asker signature, receipts and the release lease cover them
|
|
11
|
+
* with no new envelope or lease field. */
|
|
12
|
+
export function messageContentDigest(kind, text, extras) {
|
|
13
|
+
const files = extras?.attachments?.length ? attachmentsDigest(extras.attachments) : null, buttons = extras?.buttonsDigest ?? null;
|
|
14
|
+
if (files === null && buttons === null)
|
|
15
|
+
return sha256(text);
|
|
16
|
+
return sha256(JSON.stringify([`agend-hub-${kind}-extras-v1`, sha256(text), files, buttons]));
|
|
17
|
+
}
|
|
18
|
+
export function personKeyString(input) { const p = validated(person, input); return `${p.realm}/${p.objectId}`; }
|
|
19
|
+
function tuple(e) {
|
|
20
|
+
return JSON.stringify(["agend-hub-ask-v1", e.v, e.issuer, e.issuerKeyId, e.messageId, e.asker.realm, e.asker.objectId,
|
|
21
|
+
e.owner.realm, e.owner.objectId, e.destinationFleetId, e.exposureId, e.roomId, e.grantId, e.grantRevision,
|
|
22
|
+
e.exposureRevision, e.revocationVersion, e.contentDigest, e.issuedAt, e.expiresAt, e.nonce]);
|
|
23
|
+
}
|
|
24
|
+
export function signAsker(input, key) {
|
|
25
|
+
const e = validateAsker({ ...input, signature: "A".repeat(86) });
|
|
26
|
+
if (key.asymmetricKeyType !== "ed25519" || key.type !== "private")
|
|
27
|
+
throw new HubProtocolError();
|
|
28
|
+
return { ...e, signature: sign(null, Buffer.from(tuple(e)), key).toString("base64url") };
|
|
29
|
+
}
|
|
30
|
+
export function verifyAsker(input, text, binding, attachments) {
|
|
31
|
+
const e = validateAsker(input), key = binding.issuerPublicKey;
|
|
32
|
+
if (key.type !== "public" || key.asymmetricKeyType !== "ed25519" || e.issuer !== binding.hubId || e.issuerKeyId !== binding.issuerKeyId
|
|
33
|
+
|| e.destinationFleetId !== binding.fleetId || personKeyString(e.owner) !== personKeyString(binding.owner)
|
|
34
|
+
|| e.contentDigest !== messageContentDigest("question", text, { attachments }) || e.revocationVersion !== binding.revocationVersion
|
|
35
|
+
|| !Number.isSafeInteger(binding.now) || e.expiresAt <= binding.now || e.issuedAt > binding.now + 5_000
|
|
36
|
+
|| e.expiresAt <= e.issuedAt || e.expiresAt - e.issuedAt > 120_000
|
|
37
|
+
|| Buffer.from(e.signature, "base64url").toString("base64url") !== e.signature
|
|
38
|
+
|| !verify(null, Buffer.from(tuple(e)), key, Buffer.from(e.signature, "base64url")))
|
|
39
|
+
throw new HubProtocolError("denied");
|
|
40
|
+
return e;
|
|
41
|
+
}
|
|
42
|
+
export function operationDigest(input) {
|
|
43
|
+
const r = validateAuthorization(input);
|
|
44
|
+
return sha256(JSON.stringify(["agend-hub-operation-v1", r.messageId, r.operationId, r.phase, r.exposureRevision,
|
|
45
|
+
r.phase === "tool" ? r.tool.name : null, r.phase === "tool" ? r.tool.argumentsDigest : null,
|
|
46
|
+
r.phase === "release-answer" ? r.answer.answerId : null, r.phase === "release-answer" ? r.answer.contentDigest : null]));
|
|
47
|
+
}
|
|
48
|
+
export function verifyLease(input, request, expected) {
|
|
49
|
+
const lease = validated(leaseSchema, input), r = validateAuthorization(request);
|
|
50
|
+
if (lease.messageId !== r.messageId || lease.operationId !== r.operationId || lease.phase !== r.phase
|
|
51
|
+
|| lease.exposureRevision !== r.exposureRevision || lease.operationDigest !== operationDigest(r)
|
|
52
|
+
|| lease.linkEpoch !== expected.linkEpoch || lease.revocationVersion !== expected.revocationVersion
|
|
53
|
+
|| lease.expiresAt <= expected.now || lease.expiresAt > expected.now + 5_000)
|
|
54
|
+
throw new HubProtocolError("stale");
|
|
55
|
+
return lease;
|
|
56
|
+
}
|
|
57
|
+
export function canonicalArguments(input) {
|
|
58
|
+
const canonical = (v, depth) => {
|
|
59
|
+
if (depth > 32)
|
|
60
|
+
throw new HubProtocolError();
|
|
61
|
+
if (v === null || typeof v === "boolean" || typeof v === "number" && Number.isFinite(v) && Math.abs(v) <= Number.MAX_SAFE_INTEGER)
|
|
62
|
+
return JSON.stringify(v);
|
|
63
|
+
if (typeof v === "string") {
|
|
64
|
+
parseStrictJson(JSON.stringify(v));
|
|
65
|
+
return JSON.stringify(v);
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(v))
|
|
68
|
+
return `[${v.map(x => canonical(x, depth + 1)).join(",")}]`;
|
|
69
|
+
if (v && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype) {
|
|
70
|
+
return `{${Object.keys(v).sort().map(k => `${canonical(k, depth + 1)}:${canonical(v[k], depth + 1)}`).join(",")}}`;
|
|
71
|
+
}
|
|
72
|
+
throw new HubProtocolError();
|
|
73
|
+
};
|
|
74
|
+
const out = canonical(input, 0);
|
|
75
|
+
if (Buffer.byteLength(out) > 64 * 1024)
|
|
76
|
+
throw new HubProtocolError();
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
export function issuerKeyId(key) { return sha256((key.type === "public" ? key : createPublicKey(key)).export({ type: "spki", format: "der" })); }
|
|
80
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/hub/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HubInitPlan } from "./types.js";
|
|
2
|
+
export interface HubBrowserMaterial {
|
|
3
|
+
certFile: string;
|
|
4
|
+
keyFile: string;
|
|
5
|
+
cleanup(): void;
|
|
6
|
+
}
|
|
7
|
+
/** Recover only material explicitly generated for this saved init plan; imported files are never owned here. */
|
|
8
|
+
export declare function recoverBrowserCertificate(home: string, origin: string, files: HubInitPlan["webTls"]): HubBrowserMaterial | null;
|
|
9
|
+
export declare function createBrowserCertificate(home: string, origin: string): Promise<HubBrowserMaterial>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** Explicit owner-requested browser certificate preparation; no network, shell, trust-store or Hub identity changes. */
|
|
2
|
+
import { generateKeyPairSync, createHash } from "node:crypto";
|
|
3
|
+
import { mkdtempSync, writeFileSync, rmSync, lstatSync, unlinkSync } from "node:fs";
|
|
4
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
5
|
+
import { isIP } from "node:net";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
import { execFile } from "../../child-process.js";
|
|
8
|
+
import { privatePath, readPrivateFile } from "../private-files.js";
|
|
9
|
+
import { checkBrowserTls } from "./browser-tls.js";
|
|
10
|
+
const digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
11
|
+
/** Recover only material explicitly generated for this saved init plan; imported files are never owned here. */
|
|
12
|
+
export function recoverBrowserCertificate(home, origin, files) {
|
|
13
|
+
if (files.generated !== true)
|
|
14
|
+
return null;
|
|
15
|
+
const dir = dirname(files.certFile);
|
|
16
|
+
if (dirname(dir) !== resolve(home) || !/^\.hub-browser-[a-zA-Z0-9]{6}$/.test(basename(dir))
|
|
17
|
+
|| files.certFile !== join(dir, "cert.pem") || files.keyFile !== join(dir, "key.pem"))
|
|
18
|
+
throw Error("browser_certificate_staging_changed");
|
|
19
|
+
const suffix = relative(home, dir);
|
|
20
|
+
privatePath(home, suffix, true);
|
|
21
|
+
const identity = lstatSync(dir);
|
|
22
|
+
const validate = () => {
|
|
23
|
+
const marker = JSON.parse(readPrivateFile(home, `${suffix}/material.json`, 1024));
|
|
24
|
+
const cert = readPrivateFile(home, `${suffix}/cert.pem`), key = readPrivateFile(home, `${suffix}/key.pem`);
|
|
25
|
+
if (marker?.v !== 1 || marker.origin !== origin || marker.certSha256 !== digest(cert) || marker.keySha256 !== digest(key))
|
|
26
|
+
throw Error("browser_certificate_staging_changed");
|
|
27
|
+
};
|
|
28
|
+
validate();
|
|
29
|
+
return { certFile: files.certFile, keyFile: files.keyFile, cleanup() {
|
|
30
|
+
let current;
|
|
31
|
+
try {
|
|
32
|
+
current = lstatSync(dir);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err.code === "ENOENT")
|
|
36
|
+
return;
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
if (!current.isDirectory() || current.isSymbolicLink() || current.ino !== identity.ino || current.dev !== identity.dev || current.uid !== identity.uid)
|
|
40
|
+
throw Error("browser_certificate_staging_changed");
|
|
41
|
+
validate();
|
|
42
|
+
rmSync(dir, { recursive: true });
|
|
43
|
+
} };
|
|
44
|
+
}
|
|
45
|
+
export async function createBrowserCertificate(home, origin) {
|
|
46
|
+
const u = new URL(origin), host = u.hostname.replace(/^\[|\]$/g, "");
|
|
47
|
+
const dns = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
|
48
|
+
if (u.protocol !== "https:" || u.username || u.password || u.search || u.hash || u.pathname !== "/"
|
|
49
|
+
|| u.origin !== origin.replace(/\/$/, "") || (!isIP(host) && !dns.test(host)))
|
|
50
|
+
throw Error("invalid_browser_origin");
|
|
51
|
+
privatePath(home, "", true);
|
|
52
|
+
const key = generateKeyPairSync("ec", { namedCurve: "prime256v1" }).privateKey.export({ type: "pkcs8", format: "pem" }).toString();
|
|
53
|
+
const dir = mkdtempSync(join(home, ".hub-browser-")), identity = lstatSync(dir);
|
|
54
|
+
const files = { certFile: join(dir, "cert.pem"), keyFile: join(dir, "key.pem"), generated: true };
|
|
55
|
+
try {
|
|
56
|
+
// OpenSSL's key loader needs a file on supported builds. Only its private path is in argv, never key bytes.
|
|
57
|
+
writeFileSync(files.keyFile, key, { flag: "wx", mode: 0o600 });
|
|
58
|
+
// LibreSSL requires a real distinguished-name section. Keep all extensions in this private, self-contained
|
|
59
|
+
// config instead of depending on the host's openssl.cnf or optional command-line extension flags.
|
|
60
|
+
const configFile = join(dir, "openssl.cnf");
|
|
61
|
+
writeFileSync(configFile, `[req]\nprompt=no\ndistinguished_name=dn\nx509_extensions=server\n[dn]\nCN=AgEnD Hub\n[server]\nsubjectAltName=${isIP(host) ? "IP" : "DNS"}:${host}\nbasicConstraints=critical,CA:FALSE\nkeyUsage=critical,digitalSignature\nextendedKeyUsage=serverAuth\n`, { flag: "wx", mode: 0o600 });
|
|
62
|
+
const { stdout: cert } = await promisify(execFile)("/usr/bin/openssl", ["req", "-new", "-x509", "-sha256", "-days", "30", "-config", configFile,
|
|
63
|
+
"-key", files.keyFile], { timeout: 10_000, maxBuffer: 64 * 1024, env: { PATH: "/usr/bin:/bin", LANG: "C" } }).catch(() => { throw Error("browser_certificate_generation_failed"); });
|
|
64
|
+
unlinkSync(configFile);
|
|
65
|
+
if (!checkBrowserTls(cert, key, u.origin, Date.now()).ok)
|
|
66
|
+
throw Error("browser_certificate_generation_failed");
|
|
67
|
+
writeFileSync(files.certFile, cert, { flag: "wx", mode: 0o600 });
|
|
68
|
+
writeFileSync(join(dir, "material.json"), JSON.stringify({ v: 1, origin: u.origin, certSha256: digest(cert), keySha256: digest(key) }), { flag: "wx", mode: 0o600 });
|
|
69
|
+
return recoverBrowserCertificate(home, u.origin, files);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const current = lstatSync(dir);
|
|
73
|
+
if (current.isDirectory() && !current.isSymbolicLink() && current.ino === identity.ino && current.dev === identity.dev)
|
|
74
|
+
rmSync(dir, { recursive: true });
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=browser-certificate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-certificate.js","sourceRoot":"","sources":["../../../src/hub/init/browser-certificate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type BrowserTlsProblem = "cert-unreadable" | "key-unreadable" | "key-mismatch" | "host-not-covered" | "not-yet-valid" | "expired" | "ca-certificate";
|
|
2
|
+
export interface BrowserTlsCheck {
|
|
3
|
+
readonly ok: boolean;
|
|
4
|
+
readonly problems: readonly BrowserTlsProblem[];
|
|
5
|
+
/** Advisory only: browsers will warn unless this certificate is trusted some other way. */
|
|
6
|
+
readonly selfSigned: boolean;
|
|
7
|
+
readonly subject?: string;
|
|
8
|
+
readonly issuer?: string;
|
|
9
|
+
readonly validTo?: string;
|
|
10
|
+
readonly fingerprint256?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Split a PEM bundle into its certificates (leaf first, as servers send them). */
|
|
13
|
+
export declare function pemCertificates(pem: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Check a certificate chain + private key for the Hub's web address. Pure: the caller reads the files. The key text is
|
|
16
|
+
* never echoed or returned.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkBrowserTls(certPem: string, keyPem: string, webOrigin: string, nowMs?: number): BrowserTlsCheck;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Hub's browser-facing HTTPS certificate (S-48, hub.md §2 "Origins, keys and bootstrap"). It is separate from the
|
|
3
|
+
* member transport certificate S1 generates: colleagues' browsers must trust it, so it comes from the operator
|
|
4
|
+
* (an organisation-issued certificate, or one their browsers are otherwise set up to trust). There is no plaintext
|
|
5
|
+
* fallback: without a usable certificate the wizard stops and the Hub stays off.
|
|
6
|
+
*/
|
|
7
|
+
import { X509Certificate, createPrivateKey } from "node:crypto";
|
|
8
|
+
import { isIP } from "node:net";
|
|
9
|
+
/** Split a PEM bundle into its certificates (leaf first, as servers send them). */
|
|
10
|
+
export function pemCertificates(pem) {
|
|
11
|
+
return pem.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g) ?? [];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check a certificate chain + private key for the Hub's web address. Pure: the caller reads the files. The key text is
|
|
15
|
+
* never echoed or returned.
|
|
16
|
+
*/
|
|
17
|
+
export function checkBrowserTls(certPem, keyPem, webOrigin, nowMs = Date.now()) {
|
|
18
|
+
const problems = [];
|
|
19
|
+
const pems = pemCertificates(certPem);
|
|
20
|
+
let leaf;
|
|
21
|
+
try {
|
|
22
|
+
if (pems.length > 0)
|
|
23
|
+
leaf = new X509Certificate(pems[0]);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
leaf = undefined;
|
|
27
|
+
}
|
|
28
|
+
if (!leaf)
|
|
29
|
+
return { ok: false, problems: ["cert-unreadable"], selfSigned: false };
|
|
30
|
+
let key;
|
|
31
|
+
try {
|
|
32
|
+
key = createPrivateKey({ key: keyPem, format: "pem" });
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
problems.push("key-unreadable");
|
|
36
|
+
}
|
|
37
|
+
if (key && !leaf.checkPrivateKey(key))
|
|
38
|
+
problems.push("key-mismatch");
|
|
39
|
+
const host = new URL(webOrigin).hostname.replace(/^\[(.*)\]$/, "$1");
|
|
40
|
+
const covered = isIP(host) ? leaf.checkIP(host) !== undefined : leaf.checkHost(host, { subject: "never" }) !== undefined;
|
|
41
|
+
if (!covered)
|
|
42
|
+
problems.push("host-not-covered");
|
|
43
|
+
if (Date.parse(leaf.validFrom) > nowMs)
|
|
44
|
+
problems.push("not-yet-valid");
|
|
45
|
+
if (Date.parse(leaf.validTo) <= nowMs)
|
|
46
|
+
problems.push("expired");
|
|
47
|
+
const selfSigned = leaf.issuer === leaf.subject && leaf.verify(leaf.publicKey);
|
|
48
|
+
// A CA-issued leaf that is itself a CA is the wrong certificate (usually the chain in the wrong order). Self-signed
|
|
49
|
+
// server certificates commonly carry CA:TRUE (openssl's default), so for them it is not a problem by itself.
|
|
50
|
+
if (leaf.ca && !selfSigned)
|
|
51
|
+
problems.push("ca-certificate");
|
|
52
|
+
return {
|
|
53
|
+
ok: problems.length === 0,
|
|
54
|
+
problems,
|
|
55
|
+
selfSigned,
|
|
56
|
+
subject: leaf.subject,
|
|
57
|
+
issuer: leaf.issuer,
|
|
58
|
+
validTo: leaf.validTo,
|
|
59
|
+
fingerprint256: leaf.fingerprint256,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=browser-tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-tls.js","sourceRoot":"","sources":["../../../src/hub/init/browser-tls.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAkB,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAsBhC,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,GAAG,CAAC,KAAK,CAAC,+DAA+D,CAAC,IAAI,EAAE,CAAC;AAC1F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,MAAc,EAAE,SAAiB,EAAE,KAAK,GAAW,IAAI,CAAC,GAAG,EAAE;IAC5G,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,IAAiC,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAElF,IAAI,GAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,GAAG,GAAG,gBAAgB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAErE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,SAAS,CAAC;IACzH,IAAI,CAAC,OAAO;QAAE,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAEhD,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK;QAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACvE,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK;QAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/E,oHAAoH;IACpH,6GAA6G;IAC7G,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC5D,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QACzB,QAAQ;QACR,UAAU;QACV,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,cAAc,EAAE,IAAI,CAAC,cAAc;KACpC,CAAC;AACJ,CAAC"}
|