@teamscala/service-boot 0.23.523 → 0.23.524
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/src/agreement-gate/agreement-lookup.ts +0 -7
- package/src/agreement-gate/authorized-emails.ts +0 -7
- package/src/agreement-gate/placeholder-strip.ts +0 -8
- package/src/agreement-gate/resolution-caches.ts +0 -5
- package/src/agreement-gate/settings.ts +0 -7
- package/src/agreement-gate/signing-session.ts +0 -8
- package/src/agreement-gate/signing-shell.ts +0 -9
- package/src/agreement-gate.ts +0 -18
- package/src/apply-logger-config.ts +1 -9
- package/src/asset-cache-key.ts +1 -5
- package/src/asset-optimize.ts +1 -7
- package/src/asset-proxy.ts +1 -10
- package/src/asset-social-card.ts +1 -9
- package/src/attach-agreement-magic.ts +0 -14
- package/src/attach-portal-members.ts +0 -17
- package/src/attach-proposal-accept.ts +0 -20
- package/src/attach-proposal-magic.ts +0 -12
- package/src/attach-transfers-upload.ts +0 -21
- package/src/auth/sign-out.ts +1 -42
- package/src/auth-gate/public-paths.ts +1 -10
- package/src/auth-gate.ts +1 -22
- package/src/bind-page-handler.ts +1 -7
- package/src/build-client-assets/build-lock.ts +1 -11
- package/src/build-client-assets/hashed-output.ts +1 -11
- package/src/build-client-assets/hydrate-bundle.ts +1 -11
- package/src/build-client-assets/manifest.ts +1 -12
- package/src/build-client-assets/source-candidates.ts +0 -17
- package/src/build-client-assets/sourcemaps-upload.ts +1 -10
- package/src/build-client-assets/styles-build.ts +1 -21
- package/src/build-client-assets.ts +1 -30
- package/src/capability-slug.ts +1 -35
- package/src/compose-page-title.ts +1 -25
- package/src/content-gate/access.ts +0 -8
- package/src/content-gate/catalog.ts +0 -23
- package/src/content-gate/config-types.ts +0 -6
- package/src/content-gate/gate-entry-clears.ts +0 -18
- package/src/content-gate/gate.ts +0 -7
- package/src/content-gate/parse-cookie.ts +0 -4
- package/src/content-gate/token.ts +0 -22
- package/src/content-page-floor.ts +0 -17
- package/src/csrf-protection.ts +1 -28
- package/src/error-page-logo.ts +0 -23
- package/src/expand-roster.ts +1 -16
- package/src/gate-ttls.ts +0 -12
- package/src/gpt-gate.ts +0 -18
- package/src/hono-error-handler.ts +0 -15
- package/src/install-harness.ts +1 -12
- package/src/install-logging.ts +1 -15
- package/src/is-react-element-type.ts +1 -11
- package/src/load-page-manifest.ts +1 -23
- package/src/load-service-install-row.ts +1 -6
- package/src/module-not-found.ts +0 -6
- package/src/mount-orpc-router.ts +0 -6
- package/src/mount-server-packages.ts +1 -8
- package/src/mount.ts +1 -4
- package/src/mutable-app-ref.ts +0 -10
- package/src/orpc-openapi-document.ts +1 -13
- package/src/orpc-openapi-gate.ts +1 -13
- package/src/page-route-shell-types.ts +1 -8
- package/src/page-server-loader-graph.ts +0 -10
- package/src/page-server-orpc/hub-mcp-client.ts +1 -7
- package/src/page-server-orpc/server-client.ts +1 -23
- package/src/pg-boss-handler-registry.ts +1 -12
- package/src/pg-boss-mount.ts +1 -8
- package/src/proposal-authorized-emails.ts +0 -32
- package/src/proposal-gate.ts +0 -11
- package/src/quiz-gate.ts +0 -22
- package/src/read-html-template.ts +1 -49
- package/src/readiness-gate.ts +0 -8
- package/src/register-api-routes.ts +1 -11
- package/src/register-crash-handlers.ts +1 -6
- package/src/register-page-routes.ts +1 -12
- package/src/register-page-server-client.ts +1 -13
- package/src/register-registry-page-route/ai-chat-prefetch.ts +1 -6
- package/src/register-registry-page-route/apply-page-branding.ts +1 -10
- package/src/register-registry-page-route/captured-loader-config.ts +1 -11
- package/src/register-registry-page-route/graph-cache.ts +1 -21
- package/src/register-registry-page-route/live-loader-config.ts +1 -22
- package/src/register-registry-page-route/meta-title.ts +1 -12
- package/src/register-registry-page-route/page-data-shared.ts +1 -12
- package/src/register-registry-page-route/prefetch-org-id.ts +1 -7
- package/src/register-registry-page-route/proposal-approval-email-token.ts +1 -11
- package/src/register-registry-page-route/proposal-brand-stamping.ts +1 -11
- package/src/register-registry-page-route/public-shell-page-data.ts +1 -8
- package/src/register-registry-page-route/region-slots-page-data.ts +1 -8
- package/src/register-registry-page-route/resolve-page-data.ts +1 -10
- package/src/register-registry-page-route/resolve-panel-page.ts +1 -10
- package/src/register-registry-page-route/resolve-request-graph.ts +1 -11
- package/src/register-registry-page-route/run-content-gates.ts +1 -10
- package/src/register-registry-page-route/single-page-data.ts +1 -9
- package/src/register-registry-page-route/stamp-session-context.ts +1 -10
- package/src/register-registry-page-route/warn-uncovered-blocks.ts +1 -8
- package/src/register-registry-page-route.ts +1 -18
- package/src/register-static-assets.ts +1 -8
- package/src/register-ws-routes.ts +1 -21
- package/src/resolve-brand-favicon.ts +0 -13
- package/src/resolve-service-port.ts +1 -50
- package/src/resolve-theme-mode.ts +1 -22
- package/src/resolvers/app-header.ts +1 -19
- package/src/resolvers/fetch-org-brand.ts +1 -10
- package/src/resolvers/portal-route-paths.ts +1 -12
- package/src/resolvers/website-by-host-map.ts +1 -7
- package/src/resource-chat-inject.ts +0 -17
- package/src/resource-not-found.ts +0 -24
- package/src/run-boot-hook-list.ts +1 -13
- package/src/run-boot-hooks.ts +1 -19
- package/src/scala-tools-currency-watchdog.ts +1 -7
- package/src/security-headers.ts +1 -7
- package/src/select-service-routes.ts +1 -17
- package/src/server-error-page.ts +0 -18
- package/src/theme-fonts-link.ts +1 -16
- package/src/transfers/presigned-upload.ts +1 -27
- package/src/two-phase-full-app.ts +0 -6
- package/src/two-phase-minimal-app.ts +0 -6
- package/src/two-phase-readiness.ts +0 -6
- package/src/types.ts +0 -3
- package/src/ui-service.ts +1 -6
- package/src/ws-boot-self-test.ts +1 -14
package/package.json
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Agreement lookup: typed first-match query over the agreements model via
|
|
7
|
-
* the page-server ORPC client.
|
|
8
|
-
*
|
|
9
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
10
|
-
* paths adjusted only.
|
|
11
4
|
*/
|
|
12
5
|
|
|
13
6
|
import { getServerClient } from "../page-server-orpc/server-client.ts";
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The agreement's authorized email sets: the signer roster (who may sign) and
|
|
7
|
-
* the roster ∪ owning/party-org members (who may view past the gate).
|
|
8
|
-
*
|
|
9
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
10
|
-
* paths adjusted only.
|
|
11
4
|
*/
|
|
12
5
|
|
|
13
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The withholding transform: drop blocks whose own text still carries an
|
|
7
|
-
* {{agreement.*}} token, recursively, so unauthed viewers never see raw
|
|
8
|
-
* placeholders.
|
|
9
|
-
*
|
|
10
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
11
|
-
* paths adjusted only.
|
|
12
4
|
*/
|
|
13
5
|
|
|
14
6
|
import type { ContentBlock } from "./signing-session.ts";
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The agreement gate's resolution caches: the page→agreement association
|
|
7
|
-
* cache, the owning/party org member-directory caches, and the event-driven
|
|
8
|
-
* invalidation (LISTEN registry_config_changed) that clears them.
|
|
9
4
|
*/
|
|
10
5
|
|
|
11
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* DB-driven display + behaviour settings for the AGREEMENT content gate
|
|
7
|
-
* (config/content-gate-agreement), plus its cookie name.
|
|
8
|
-
*
|
|
9
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
10
|
-
* paths adjusted only.
|
|
11
4
|
*/
|
|
12
5
|
|
|
13
6
|
import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The verified signer's signing session: gate-block discovery across regions,
|
|
7
|
-
* roster/party session construction (signer vs view-only org member), and
|
|
8
|
-
* seeding of the session into every SignatureField.
|
|
9
|
-
*
|
|
10
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
11
|
-
* paths adjusted only.
|
|
12
4
|
*/
|
|
13
5
|
|
|
14
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* New-flow signing-shell injection (no pre-placed gate required): agreement
|
|
7
|
-
* meta stashing, body-content discovery, the SignIn gate block builder, and
|
|
8
|
-
* the DB-driven signing shell (config/agreement-signing-shell) with its
|
|
9
|
-
* hardcoded fallback.
|
|
10
|
-
*
|
|
11
|
-
* Split out of agreement-gate.ts (909 lines) — byte-for-byte move; import
|
|
12
|
-
* paths adjusted only.
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
6
|
/**
|
package/src/agreement-gate.ts
CHANGED
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The AGREEMENT content gate, expressed as config for the content-gate primitive
|
|
7
|
-
* (content-gate/). The agreement-specific bits: which resource (the placed
|
|
8
|
-
* SignIn gate block's id), who's authorized (the signer roster), what to seed
|
|
9
|
-
* (the verified signer's signing session into every SignatureField), and how to
|
|
10
|
-
* withhold (strip the gate region to gate-only + strip {{agreement.*}} chrome).
|
|
11
|
-
* The engine handles cookie/token/verify/orchestration.
|
|
12
|
-
*
|
|
13
|
-
* The signing logic (buildSigningSession, seedSigningBlocks, roster expansion,
|
|
14
|
-
* placeholder strip) is preserved verbatim from the former gate-agreement-
|
|
15
|
-
* content.ts — only the cookie/token orchestration moved into the shared engine.
|
|
16
|
-
*
|
|
17
|
-
* This module holds the two exported configs (agreementGateConfig +
|
|
18
|
-
* agreementAccessConfig). The machinery lives as siblings under
|
|
19
|
-
* ./agreement-gate/ (settings, agreement-lookup, signing-session,
|
|
20
|
-
* placeholder-strip, signing-shell, authorized-emails) — split when the
|
|
21
|
-
* parent held them all at 909 lines.
|
|
22
4
|
*/
|
|
23
5
|
|
|
24
6
|
import type { AccessConfig, ContentGateConfig } from "./content-gate/config-types.ts";
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Late-stage logger configuration — runs AFTER Registry is loaded (the boot
|
|
7
|
-
* pipeline's `apply-logger-config` phase), injecting the DB-driven settings
|
|
8
|
-
* into the logger primitive. Split from install-logging.ts under
|
|
9
|
-
* single-purpose-file: the early bootstrap (hardcoded defaults, primitive
|
|
10
|
-
* injection) and this late reconfiguration are two phases, and the guard
|
|
11
|
-
* counts them as two export groups in one file.
|
|
12
4
|
*/
|
|
13
5
|
|
|
14
6
|
import { setMinLevel } from "@teamscala/logger/creator";
|
package/src/asset-cache-key.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* ETag derivation for the asset proxy that incorporates the negotiated
|
|
7
|
-
* image format so per-Accept variants cache independently.
|
|
8
4
|
*/
|
|
9
5
|
|
|
10
6
|
const SKIP_FORMATS = new Set(["webp", "avif", "gif", "svg", "ico"]);
|
package/src/asset-optimize.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* On-the-fly image optimisation for the asset proxy. Converts stored
|
|
7
|
-
* PNG/JPEG to WebP or AVIF when the browser signals support, using
|
|
8
|
-
* @teamscala/image-optimizer's compressImage primitive. Returns null
|
|
9
|
-
* on failure so the caller can fall back to the original stream.
|
|
10
4
|
*/
|
|
11
5
|
|
|
12
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
package/src/asset-proxy.ts
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Same-origin S3 asset proxy with on-the-fly image optimisation.
|
|
7
|
-
* Streams objects from the configured S3 bucket, converting PNG/JPEG
|
|
8
|
-
* to WebP/AVIF when the browser declares support via Accept header.
|
|
9
|
-
* Returns 404 for missing keys, 502 for S3 failures. Never redirects.
|
|
10
|
-
* Every non-2xx exit records which stage failed through the app logger:
|
|
11
|
-
* a 404 and a 502 are indistinguishable at the socket, so the fault plane
|
|
12
|
-
* (credential resolution vs store side) is only observable in the log.
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
package/src/asset-social-card.ts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Dynamic-import wrapper around image-optimizer's in-process sharp
|
|
7
|
-
* social-card op. Mirrors asset-optimize.ts's optional-dependency shape:
|
|
8
|
-
* services without image-optimizer installed transparently get null and
|
|
9
|
-
* fall back to the raw asset stream. In-process (not HTTP) because the
|
|
10
|
-
* og:image transform is a cold path per shared link — no auth handshake,
|
|
11
|
-
* no per-consumer service config.
|
|
12
4
|
*/
|
|
13
5
|
|
|
14
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The agreement MAGIC-LINK endpoint. A recipient who clicks an emailed
|
|
7
|
-
* "Review & sign" link — which carries a pre-authorised, signed ag_token for
|
|
8
|
-
* THEIR party — lands here: the token is verified for the agreement, the
|
|
9
|
-
* ag_token cookie is set on the shared parent domain, and the browser is
|
|
10
|
-
* 302-redirected straight into the signing page. No email-entry gate, no OTP —
|
|
11
|
-
* "came from our email" IS the proof of identity, exactly like the
|
|
12
|
-
* proposal-accept hand-off (attach-proposal-accept.ts).
|
|
13
|
-
*
|
|
14
|
-
* The token is the same HMAC ag_token the gate verifies (30-min TTL, scoped to
|
|
15
|
-
* {agreementId, email}); an invalid/expired/forged token sets no cookie and the
|
|
16
|
-
* destination page simply shows the normal email gate. GET so it is a plain
|
|
17
|
-
* clickable link in an email.
|
|
18
4
|
*/
|
|
19
5
|
|
|
20
6
|
import type { Hono } from "hono";
|
|
@@ -1,23 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Portal-secured member directory endpoint. Resolves members of an org via a
|
|
7
|
-
* parameterized raw join over better_auth_member + "user" — NOT the typed
|
|
8
|
-
* `member` ORPC model, which is deliberately omitted from the portal's
|
|
9
|
-
* service_schema (security: the raw table is not exposed as a typed CRUD
|
|
10
|
-
* surface). Mirrors the agreement-gate.ts:109-150 precedent.
|
|
11
|
-
*
|
|
12
|
-
* The portal's auth middleware (better-auth-cookie) gates the endpoint — only
|
|
13
|
-
* authenticated users can call it. The orgId comes from the caller's context
|
|
14
|
-
* (the portal resolves it from the session + passes it).
|
|
15
|
-
*
|
|
16
|
-
* Endpoint: GET /api/portal/members?orgId=<uuid>
|
|
17
|
-
* - orgId omitted: super-admin all-orgs mode (returns every member across
|
|
18
|
-
* all orgs, strictly gated to super-admin via getSession; used by the
|
|
19
|
-
* "View As" impersonation dropdown).
|
|
20
|
-
* Response: { members: Array<{ id, user_id, organization_id, role, email, name, image }> }
|
|
21
4
|
*/
|
|
22
5
|
|
|
23
6
|
import type { Hono } from "hono";
|
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The proposal ACCEPT endpoint. A viewer who has passed the proposal gate (holds
|
|
7
|
-
* a valid prop_token) POSTs {proposalId} here to accept; the server generates a
|
|
8
|
-
* signing document from the proposal (createAgreementFromProposal) and
|
|
9
|
-
* 302-redirects them straight into signing it on the sign site. This replaces
|
|
10
|
-
* the old mailto CTA. Mounted BEFORE the auth gate so it is publicly reachable —
|
|
11
|
-
* the prop_token (not a login) is the proof of identity, exactly like the
|
|
12
|
-
* content-gate access endpoint.
|
|
13
|
-
*
|
|
14
|
-
* Single sign-on across the journey: the viewer already proved their email at
|
|
15
|
-
* the proposal gate (prop_token), so we MUST NOT make them re-enter it on the
|
|
16
|
-
* sign site. Before redirecting, we mint the agreement's ag_token for that same
|
|
17
|
-
* verified email and set it on the SHARED parent domain (Domain=.scala.business)
|
|
18
|
-
* so the browser carries it from proposals.scala.business to sign.scala.business
|
|
19
|
-
* — the agreement gate then auto-reveals + seeds the signing session with zero
|
|
20
|
-
* extra prompts. This requires both hosts to resolve the SAME token secret
|
|
21
|
-
* (AUTH_SECRET→ENCRYPTION_KEY→DATABASE_URL): scala-sign must carry ENCRYPTION_KEY
|
|
22
|
-
* (also required to decrypt the org's Stripe key on full sign), so both hosts
|
|
23
|
-
* land on ENCRYPTION_KEY and the carried token verifies.
|
|
24
4
|
*/
|
|
25
5
|
|
|
26
6
|
import type { Hono } from "hono";
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The proposal MAGIC-LINK endpoint — the proposal twin of attach-agreement-magic.
|
|
7
|
-
* A recipient who clicks an emailed "View your proposal" link (carrying a signed,
|
|
8
|
-
* per-recipient prop_token) lands here: the token is verified for the proposal,
|
|
9
|
-
* the prop_token cookie is set, and the browser is 302-redirected straight into
|
|
10
|
-
* the proposal page. No email-entry gate, no OTP. An invalid/expired token sets
|
|
11
|
-
* no cookie and the page falls through to the normal email gate.
|
|
12
|
-
*
|
|
13
|
-
* The prop_token is host-scoped (proposals are served on the proposals host only),
|
|
14
|
-
* unlike the agreement ag_token which spans .scala.business for the proposal→sign
|
|
15
|
-
* hand-off. GET so it is a plain clickable link in an email.
|
|
16
4
|
*/
|
|
17
5
|
|
|
18
6
|
import type { Hono } from "hono";
|
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Authenticated asset upload — POST /api/transfers/upload. Restores the
|
|
7
|
-
* handler deleted with @teamscala/server-files (commit ca5643ef); avatar/logo
|
|
8
|
-
* upload had 404'd on every service since. Writes to S3 via
|
|
9
|
-
* @teamscala/object-storage/create/write-ops and returns the SERVABLE URL
|
|
10
|
-
* (`/api/assets/<key>`) the client persists into avatar_url/logo_url — the
|
|
11
|
-
* stored value is the servable value (single-logo-pathway), so display code
|
|
12
|
-
* reads the column with no rewriting. Self-authenticates (getSession) so it
|
|
13
|
-
* mounts BEFORE the auth gate.
|
|
14
|
-
*
|
|
15
|
-
* Key scheme is USER-scoped (`users/<userId>/<type>/<file>-<ts>.<ext>`) per
|
|
16
|
-
* the operator ruling: a profile picture belongs to the individual, not any
|
|
17
|
-
* org (the prior handler's org-scoped `<orgId>/avatars/...` encoded the
|
|
18
|
-
* uploading org into a personal asset). Spec + history:
|
|
19
|
-
* `reference/asset-upload-system.md`.
|
|
20
|
-
*
|
|
21
|
-
* `thumbUrl` mirrors `url` — the full image is served for both; a separate
|
|
22
|
-
* generated thumbnail is a future refinement (the prior handler generated
|
|
23
|
-
* one, but the image-resize dependency is not wired here yet and a missing
|
|
24
|
-
* thumb must not block the upload restoring).
|
|
25
4
|
*/
|
|
26
5
|
import type { Hono } from "hono";
|
|
27
6
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
package/src/auth/sign-out.ts
CHANGED
|
@@ -1,47 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
|
-
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The fn.auth.signOut procedure body (api_route `fn-auth-sign-out`, authed:
|
|
7
|
-
* context). It is the host-side sign-out the Button logout action calls
|
|
8
|
-
* through the generated ORPC client node, replacing the raw browser POST to
|
|
9
|
-
* /api/auth/sign-out. It takes no input — sign-out has no fields — so the
|
|
10
|
-
* generated node is called as `orpcClient.fn.auth.signOut()`, the same no-arg
|
|
11
|
-
* shape as fn.chat.health.
|
|
12
|
-
*
|
|
13
|
-
* WHY A PROCEDURE, NOT THE RAW FETCH. The old client called
|
|
14
|
-
* `/api/auth/sign-out` directly. That path is only served when the host is
|
|
15
|
-
* running the auth gate's `/api/auth/*` forward or a local BetterAuth handler,
|
|
16
|
-
* and it is a bare string path the client hard-codes — a second, unnamed
|
|
17
|
-
* statement of "where sign-out lives". Declaring it as an api_route procedure
|
|
18
|
-
* gives it the one home (the registry row) the rest of the auth surface uses,
|
|
19
|
-
* and the generated node carries the path.
|
|
20
|
-
*
|
|
21
|
-
* WHAT IT DOES, IN ORDER, so server-side behaviour is UNCHANGED from the
|
|
22
|
-
* forwarded POST:
|
|
23
|
-
* 1. Revoke the caller's session through the SAME BetterAuth instance the
|
|
24
|
-
* session-read path uses (getAuth() — the bridge auth-gate installs, so
|
|
25
|
-
* it validates through the identical factory). This deletes the session
|
|
26
|
-
* row and returns the Set-Cookie headers that clear it.
|
|
27
|
-
* 2. When SCALA_OTP_URL is set — centralised auth, per otp-centralised-via-
|
|
28
|
-
* otp-service — forward the same POST to scala-otp's /api/auth/sign-out
|
|
29
|
-
* with the caller's cookie, so the central service clears the shared
|
|
30
|
-
* Domain=.scala.business session too. The local revoke alone would leave
|
|
31
|
-
* the central session alive. The caller's cookie is carried forward and
|
|
32
|
-
* scala-otp's response status is checked, so a central refusal is reported
|
|
33
|
-
* rather than swallowed — the same POST the /api/auth/* forward in
|
|
34
|
-
* auth-gate performs.
|
|
35
|
-
*
|
|
36
|
-
* HONEST RESIDUAL: the ORPC response is JSON, so the Set-Cookie headers
|
|
37
|
-
* BetterAuth returns on its Response cannot ride back to the browser through
|
|
38
|
-
* this procedure. The session is revoked in the database on both sides, and
|
|
39
|
-
* the caller redirects to the sign-in path, so the browser presents a
|
|
40
|
-
* revoked-and-deleted session token on its next request and the auth gate
|
|
41
|
-
* rejects it — the same observable outcome as the forwarded POST, whose
|
|
42
|
-
* cleared cookie was an optimisation. Clearing the cookie explicitly is the
|
|
43
|
-
* caller's business (the raw /api/auth/clear-stale-cookies route), not this
|
|
44
|
-
* procedure's.
|
|
3
|
+
* @status handwritten
|
|
45
4
|
*/
|
|
46
5
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
47
6
|
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The auth gate's public-path surface: sign-in paths, the static-asset
|
|
7
|
-
* extension predicate, and the public infra prefixes/paths (self-authenticating
|
|
8
|
-
* service-to-service surfaces, dev-host infra reads, and the access-gate
|
|
9
|
-
* rejection target).
|
|
10
|
-
*
|
|
11
|
-
* Split out of auth-gate.ts (436 lines) — byte-for-byte move; import paths
|
|
12
|
-
* adjusted only.
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
6
|
export const SIGN_IN_PATHS = new Set([
|
package/src/auth-gate.ts
CHANGED
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Auth middleware factory. Three modes, same BetterAuth email-OTP mechanism:
|
|
7
|
-
*
|
|
8
|
-
* service_install.auth values:
|
|
9
|
-
* - omitted | "none" → no gate, no handler (scala-public, scala-sign)
|
|
10
|
-
* - "better-auth-cookie" → full session auth: mount handler + session gate
|
|
11
|
-
* - "email-otp-only" → mount handler (OTP send/verify), no session gate
|
|
12
|
-
*
|
|
13
|
-
* The sign-in block determines the UX per mode:
|
|
14
|
-
* - "full" → email → OTP → session → portal selection (portal, agents, docs, gpt)
|
|
15
|
-
* - "email-gate" → email → OTP → verify-only, no session (forms, proposals, quiz)
|
|
16
|
-
* - "capture-only" → email field only, no OTP (sign)
|
|
17
|
-
*
|
|
18
|
-
* There is NO localhost bypass: 127.0.0.1 is gated identically to the tunnel
|
|
19
|
-
* (no session → /sign-in). Tools needing an authed view sign in
|
|
20
|
-
* (getSuperAdminSessionCookie); the dev OTP is DB-readable.
|
|
21
|
-
*
|
|
22
|
-
* When SCALA_OTP_URL is set, /api/auth/* forwards to the centralised
|
|
23
|
-
* scala-otp service (per otp-centralised-via-otp-service). Otherwise
|
|
24
|
-
* the local better-auth handler is used (dev-host fallback).
|
|
25
4
|
*/
|
|
26
5
|
|
|
27
6
|
/**
|
package/src/bind-page-handler.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Calls a createPageHandler() handler with the per-request extras the
|
|
7
|
-
* SSR pipeline needs: the resolved userId/orgId (from localhost-bypass
|
|
8
|
-
* or better-auth-cookie), and the htmlTemplate. Shared by the regions
|
|
9
|
-
* and page_slug shell variants.
|
|
10
4
|
*/
|
|
11
5
|
|
|
12
6
|
// Per-page root.props.maxWidth (the canonical mechanism) centers any page at the chosen width via inline styles — already hydration-safe
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The host-wide client-build lock of the client-asset build: serialises the
|
|
7
|
-
* heavy boot-time client build across ALL kind:ui services
|
|
8
|
-
* (client-asset-builds-serialize-via-lock), with a DB-driven TTL that
|
|
9
|
-
* fail-softs to a hardcoded default.
|
|
10
|
-
*
|
|
11
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
12
|
-
* siblings. Byte-for-byte move from the parent — imports adjusted, nothing
|
|
13
|
-
* else.
|
|
14
4
|
*/
|
|
15
5
|
|
|
16
6
|
import { join } from "node:path";
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Content-hashed output housekeeping for the client-asset build: the
|
|
7
|
-
* short content hash stamped into hashed filenames, and removal of stale
|
|
8
|
-
* hashed files from a previous build so dist/client/ never accumulates
|
|
9
|
-
* dead outputs.
|
|
10
|
-
*
|
|
11
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
12
|
-
* siblings. Byte-for-byte move from the parent except createHash →
|
|
13
|
-
* Bun.CryptoHasher (bun-native-crypto guard; identical digest output).
|
|
14
4
|
*/
|
|
15
5
|
|
|
16
6
|
import { readdir, rm } from "node:fs/promises";
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The hydrate JS bundle unit of the client-asset build: Bun.build over
|
|
7
|
-
* src/entry-client.ts with the resilient-block-imports plugin (dead block
|
|
8
|
-
* imports degrade at runtime instead of crash-looping the service), the
|
|
9
|
-
* post-build dead-facade gate, stale-chunk removal, and source-map upload.
|
|
10
|
-
*
|
|
11
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
12
|
-
* siblings. Byte-for-byte move from the parent — imports adjusted, nothing
|
|
13
|
-
* else.
|
|
14
4
|
*/
|
|
15
5
|
|
|
16
6
|
// Externalize an unresolvable @teamscala/* block import (a deactivated block_schema whose manifest regen never propagated) or a broken
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The asset-manifest unit of the client-asset build: the AssetManifest shape,
|
|
7
|
-
* its read/write, the last-failure tombstone status read the runtime surfaces,
|
|
8
|
-
* and the first-boot fallback paths.
|
|
9
|
-
*
|
|
10
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
11
|
-
* siblings — the file held six concerns (manifest, hashed output, hydrate
|
|
12
|
-
* bundle, source-map upload, stylesheet build, fingerprint, lock, orchestration).
|
|
13
|
-
*
|
|
14
|
-
* Byte-for-byte move from the parent — imports adjusted, nothing else.
|
|
15
4
|
*/
|
|
16
5
|
|
|
17
6
|
import { join } from "node:path";
|
|
@@ -1,23 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Tailwind source-candidate scanning for the client CSS build.
|
|
7
|
-
*
|
|
8
|
-
* Split out of build-client-assets.ts (1221 lines, six concerns). Owns ONE
|
|
9
|
-
* concern: turning the resolved `@source` directories into the candidate token
|
|
10
|
-
* set Tailwind's `build()` consumes.
|
|
11
|
-
*
|
|
12
|
-
* Why it exists at all, preserved from the original: Tailwind v4's low-level
|
|
13
|
-
* `compile()` does NOT scan content, and @tailwindcss/oxide's native Scanner is
|
|
14
|
-
* not a dependency of the bare `tailwindcss` lib — only of the integration
|
|
15
|
-
* packages. So the tokens are extracted here. Over-extraction is safe, because
|
|
16
|
-
* `build()` ignores any token that is not a valid utility. Dropping this scan is
|
|
17
|
-
* what shipped an unstyled page to the operator's tablet on 2026-06-13; it is
|
|
18
|
-
* enforced by `css-build-scans-source-candidates`.
|
|
19
|
-
*
|
|
20
|
-
* Byte-for-byte move — imports adjusted, nothing else.
|
|
21
4
|
*/
|
|
22
5
|
|
|
23
6
|
import { resolve } from "node:path";
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Upload source maps to GlitchTip via the official `glitchtip-cli` debug-ID
|
|
7
|
-
* flow, then RETAIN the maps outside the served root so a failed upload is
|
|
8
|
-
* retryable on a later boot.
|
|
9
|
-
*
|
|
10
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
11
|
-
* siblings. Byte-for-byte move from the parent — imports adjusted, nothing
|
|
12
|
-
* else.
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
6
|
/**
|
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* The Tailwind stylesheet unit of the client-asset build: Bun-native
|
|
7
|
-
* stylesheet resolution returning RAW content, stripping of remote
|
|
8
|
-
* (CSP-forbidden) @imports, and the content-hashed styles-<hash>.css
|
|
9
|
-
* build.
|
|
10
|
-
*
|
|
11
|
-
* NESTED @IMPORTS ARE THE SUPPLIER'S JOB: tailwind 4.3.3's compile()
|
|
12
|
-
* re-invokes loadStylesheet for every @import INSIDE loaded content and
|
|
13
|
-
* splices the loaded nodes into the tree (verified in the installed
|
|
14
|
-
* dist source — the dr() recursion, depth-capped at 100), so a present
|
|
15
|
-
* nested leaf is inlined by the supplier and a missing one throws at
|
|
16
|
-
* compile; the suite pins both. The 2026-07-05 dropped-leaf outage was
|
|
17
|
-
* guarded by an in-process flattener here; with the supplier recursion
|
|
18
|
-
* verified the flattener is a second owner of the same fact and is
|
|
19
|
-
* deleted.
|
|
20
|
-
*
|
|
21
|
-
* Split out of build-client-assets.ts (962 lines) alongside its build
|
|
22
|
-
* siblings. Byte-for-byte move from the parent — imports adjusted, nothing
|
|
23
|
-
* else.
|
|
24
4
|
*/
|
|
25
5
|
|
|
26
6
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -1,35 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @system
|
|
2
|
+
* @system service-boot
|
|
3
3
|
* @status handwritten
|
|
4
|
-
* @edit edit directly
|
|
5
|
-
*
|
|
6
|
-
* Builds the per-service client bundle and stylesheet into `dist/client/`
|
|
7
|
-
* at UI-service boot time. Outputs are content-hashed so deployments
|
|
8
|
-
* naturally cache-bust:
|
|
9
|
-
*
|
|
10
|
-
* src/entry-client.ts ──bun build──> dist/client/hydrate-<hash>.js
|
|
11
|
-
* src/app.css ──tailwindcss──> dist/client/styles-<hash>.css
|
|
12
|
-
* (and) dist/client/asset-manifest.json
|
|
13
|
-
*
|
|
14
|
-
* The HTML template references `{{stylesPath}}` / `{{hydratePath}}` —
|
|
15
|
-
* read-html-template.ts substitutes from the manifest at template-read
|
|
16
|
-
* time. Bytes-level changes → new hash → new URL → browser refetch.
|
|
17
|
-
* Without this, `cache-control: immutable` on a fixed filename means
|
|
18
|
-
* returning visitors keep their stale copy forever.
|
|
19
|
-
*
|
|
20
|
-
* This module is the ORCHESTRATION unit: host-wide lock → parallel
|
|
21
|
-
* hydrate/CSS builds → manifest write (or failure tombstone). The
|
|
22
|
-
* build runs on EVERY boot: the content-fingerprint skip cache and its
|
|
23
|
-
* closure-walking hashers (input-fingerprint.ts, input-hashing.ts) are
|
|
24
|
-
* deleted. A skip is the only path that can serve a stale bundle, and
|
|
25
|
-
* it has done so twice (the mtime skip that baked stale bundles until
|
|
26
|
-
* the fingerprint replaced it, 2026-06-14) — no skip is the one shape
|
|
27
|
-
* that cannot skip wrongly, at the cost of a bounded per-boot build
|
|
28
|
-
* serialised by the host-wide lock below. The individual concerns live
|
|
29
|
-
* as siblings under ./build-client-assets/
|
|
30
|
-
* (source-candidates, manifest, hashed-output, hydrate-bundle,
|
|
31
|
-
* sourcemaps-upload, styles-build, build-lock)
|
|
32
|
-
* — split when the parent held them all at 962 lines.
|
|
33
4
|
*/
|
|
34
5
|
|
|
35
6
|
// Each build is wrapped in its own catch so a JS bundle failure (e.g. transient cross-package export drift) doesn't take down the service
|