You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(webapp): address review on per-org basin migration
- Use `org.id` (cuid, fixed-length, unique-by-construction) as the
basin-name suffix instead of a truncated `org.slug`. The slug
approach could silently collide two orgs whose slugs share a prefix
past the truncation point, since the create call treats S2's 409 as
success — a real cross-tenant isolation risk.
- `resolveRetentionForOrg` now distinguishes "billing not configured"
from "billing call failed". OSS / self-hosted installs (no billing
client) get `defaultRetention()` and the worker job converges; cloud
installs that experience a transient billing failure throw and get
retried by redis-worker. Previously every install without billing
hit a permafail loop.
- `reconfigureBasinForOrg` throws when no S2 access token is
configured instead of silently returning, so a misconfigured cloud
install surfaces as a worker failure rather than stale retention.
- Duration env vars (`*_RETENTION*`, `*_DELETE_ON_EMPTY_MIN_AGE`)
validated at boot via a `durationString()` Zod schema, so a
misconfigured value fails fast at startup instead of at first basin
operation.
- Admin reconfigure route's `retention` body field validated against
the same duration shape — bad input is now a clean 400 rather than
a 500 from `parseDuration`.
- Extract duration parsing into a shared `duration.server.ts` so the
env validator and the provisioner share one source of truth.
Verified end-to-end with chat.agent locally — fresh chat lands in the
per-org basin, no leakage to the global fallback.
`[streamBasinProvisioner] REALTIME_STREAMS_BASIN_NAME_PREFIX + REALTIME_STREAMS_BASIN_NAME_ENV too long: head="${head}" leaves no room for the org slug (budget=${budget}). Shorten the prefix or env-name values.`
72
-
);
73
-
}
74
-
constslug=org.slug.slice(0,budget);
75
-
return`${head}${slug}`;
69
+
return`${prefix}-${envName}-org-${org.id}`;
76
70
}
77
71
78
72
typeProvisionInput={
79
73
id: string;
80
-
slug: string;
81
74
/// Duration string passed straight to S2. Defaults to
82
75
/// `defaultRetention()` when omitted. Caller decides; the provisioner
83
76
/// has no opinion about what retention is appropriate.
@@ -156,7 +149,15 @@ export async function reconfigureBasinForOrg(
0 commit comments