fix(owletto-backend): resolve *.lobu.ai as org subdomain under AUTH_COOKIE_DOMAIN#224
Merged
Merged
Conversation
…OOKIE_DOMAIN PR #214 set up wildcard cert/ingress, AUTH_COOKIE_DOMAIN=.lobu.ai, and BetterAuth wildcard trust so {org}.lobu.ai could carry sessions. But the middleware that actually populates `subdomainOrg` keyed off the PUBLIC_WEB_URL hostname (app.lobu.ai), so `acme.lobu.ai` didn't match `.app.lobu.ai` and the slug was never extracted — only *.app.lobu.ai worked. - Add getSubdomainZone() + extractSubdomainOrg() helpers that prefer AUTH_COOKIE_DOMAIN as the zone and fall back to the PUBLIC_WEB_URL hostname for deployments without a cookie zone. - Update the subdomain middleware to use the zone helpers, with port stripping and case-insensitive matching. - Extend the CORS allow-list to trust the cookie zone apex and its wildcard subdomains so the bare lobu.ai landing and org subdomains can call app.lobu.ai. - 13 new tests covering zone selection, reserved-subdomain skip, multi-label rejection, port handling, and case-insensitivity.
buremba
pushed a commit
that referenced
this pull request
Apr 23, 2026
Second pass on the 2-week PR review. Five more gaps closed: - gateway: unit tests for verifyOwnedAgentAccess covering owner, cross-tenant, cross-platform, agent-scoped, admin-bypass, unknown-agent, and external OAuth mismatches (#285 follow-up). Closes the test hole in the cross-tenant ownership guard. - owletto-backend: validate each CSP frame-ancestor entry against a strict host-source / scheme-source grammar before joining (#246 follow-up). Malformed env entries like `https:// lobu.ai` are now dropped instead of silently rendered into the directive. - owletto-backend: introduce normalizeHost() in utils/public-origin and use it from getSubdomainZone, extractSubdomainOrg, getCanonicalRedirectUrl, and the BetterAuth trustedOrigins wiring (#234/#224/#214 follow-up). Unifies the ad-hoc .toLowerCase()/.replace() patterns and adds IDN→punycode so `müller.lobu.ai` matches the ASCII zone configured in env. - owletto-backend: redact member emails that surface via template_data and tab template_data in resolve_path, not only on the single resolved entity (#309 follow-up). A dashboard data source that enumerates $member entities no longer leaks emails to non-admin callers. New utils/member-redaction helper plus unit coverage. - owletto-backend: treat #311 as already closed — ToolContext.memberRole is `string | null` (required, not optional), so TypeScript already catches future literal omissions at construction.
buremba
pushed a commit
that referenced
this pull request
Apr 23, 2026
Second pass on the 2-week PR review. Five more gaps closed: - gateway: unit tests for verifyOwnedAgentAccess covering owner, cross-tenant, cross-platform, agent-scoped, admin-bypass, unknown-agent, and external OAuth mismatches (#285 follow-up). Closes the test hole in the cross-tenant ownership guard. - owletto-backend: validate each CSP frame-ancestor entry against a strict host-source / scheme-source grammar before joining (#246 follow-up). Malformed env entries like `https:// lobu.ai` are now dropped instead of silently rendered into the directive. - owletto-backend: introduce normalizeHost() in utils/public-origin and use it from getSubdomainZone, extractSubdomainOrg, getCanonicalRedirectUrl, and the BetterAuth trustedOrigins wiring (#234/#224/#214 follow-up). Unifies the ad-hoc .toLowerCase()/.replace() patterns and adds IDN→punycode so `müller.lobu.ai` matches the ASCII zone configured in env. - owletto-backend: redact member emails that surface via template_data and tab template_data in resolve_path, not only on the single resolved entity (#309 follow-up). A dashboard data source that enumerates $member entities no longer leaks emails to non-admin callers. New utils/member-redaction helper plus unit coverage. - owletto-backend: treat #311 as already closed — ToolContext.memberRole is `string | null` (required, not optional), so TypeScript already catches future literal omissions at construction.
buremba
added a commit
that referenced
this pull request
Apr 23, 2026
…instr guard, MCP join rate-limit) (#325) * fix: address gaps found in post-merge review of last 2 weeks of PRs Follow-ups from an aggregated teammate review of 128 PRs merged between 2026-04-09 and 2026-04-23. Five concrete gaps patched: - worker: constrain UploadUserFile to the workspace root (#203 follow-up). path.join allowed `../` and absolute paths to escape the workspace. Now resolves and rejects anything outside workspaceDir when one is set. - core: flip Sentry sendDefaultPii to false (#172 follow-up). User content and identifiers flow through this stack; the schema has no scrubbing so PII-by-default was unsafe. - gateway: make SlackInstructionProvider extend BaseInstructionProvider (#269 follow-up). Sibling Skills/Network providers are wrapped in a try/catch that returns "" on error; Slack was bypassing it and would crash session-context assembly if listConnections threw. - owletto-backend: rate-limit the join_organization MCP tool to match the REST endpoint (#296 follow-up). Keyed on userId since MCP calls don't carry a client IP. Skipped one reviewer finding: removing the process.env fallback for API keys at worker.ts:1099/1109 (the inconsistency with #225 base-URL code). Embedded/dev workers depend on that fallback since credentialStore is only populated from gateway-supplied session context. * fix: address remaining gaps from post-merge review Second pass on the 2-week PR review. Five more gaps closed: - gateway: unit tests for verifyOwnedAgentAccess covering owner, cross-tenant, cross-platform, agent-scoped, admin-bypass, unknown-agent, and external OAuth mismatches (#285 follow-up). Closes the test hole in the cross-tenant ownership guard. - owletto-backend: validate each CSP frame-ancestor entry against a strict host-source / scheme-source grammar before joining (#246 follow-up). Malformed env entries like `https:// lobu.ai` are now dropped instead of silently rendered into the directive. - owletto-backend: introduce normalizeHost() in utils/public-origin and use it from getSubdomainZone, extractSubdomainOrg, getCanonicalRedirectUrl, and the BetterAuth trustedOrigins wiring (#234/#224/#214 follow-up). Unifies the ad-hoc .toLowerCase()/.replace() patterns and adds IDN→punycode so `müller.lobu.ai` matches the ASCII zone configured in env. - owletto-backend: redact member emails that surface via template_data and tab template_data in resolve_path, not only on the single resolved entity (#309 follow-up). A dashboard data source that enumerates $member entities no longer leaks emails to non-admin callers. New utils/member-redaction helper plus unit coverage. - owletto-backend: treat #311 as already closed — ToolContext.memberRole is `string | null` (required, not optional), so TypeScript already catches future literal omissions at construction. --------- Co-authored-by: Claude <noreply@anthropic.com>
buremba
added a commit
that referenced
this pull request
May 26, 2026
* chore: bump packages/owletto pointer to 2ffdefa Picks up: fix(oauth): frame the device consent page as an access request when arriving via a link (#224) Before: b3d3a64 After: 2ffdefa * style(cli): biome-format login-email + oauth tests These landed format-dirty via #1073 (the pre-commit --write didn't reach the committed blob), turning the format-lint check red on main. Expand the inline arrays/objects to match `biome format`. Verified clean with the exact CI command (biome format --config-path config/biome.config.json .). No logic change. Folded into this pointer-bump PR since it was blocked on the same red.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #214 set up the infra (wildcard cert/ingress,
AUTH_COOKIE_DOMAIN=.lobu.ai, BetterAuth wildcard trust, canonical-redirect cookie-zone preservation) so{org}.lobu.aicould carry sessions — but the middleware that actually populatessubdomainOrgstill keyed off thePUBLIC_WEB_URLhostname (app.lobu.ai).acme.lobu.aidoesn't end with.app.lobu.ai, so the slug was never extracted and only*.app.lobu.aiworked.getSubdomainZone()+extractSubdomainOrg()helpers that preferAUTH_COOKIE_DOMAINas the zone and fall back to thePUBLIC_WEB_URLhostname for deployments without a cookie zonepackages/owletto-backend/src/index.ts) to use the zone helpers — port stripping, case-insensitive matchingisAllowedCorsOriginso the cookie-zone apex (lobu.ai) and its wildcard subdomains are trusted CORS origins, enabling the bare landing site and org subdomains to callapp.lobu.aiTest plan
bun run --cwd packages/owletto-backend vitest run src/utils/__tests__/public-origin.test.ts— 18/18 passbun run typecheck— cleanhttps://acme.lobu.ai/mcp/tools/listand confirm it resolves to theacmeorg (no:orgSlugin URL needed)https://lobu.ai(apex) can still fetch fromhttps://app.lobu.ai(CORS preflight passes)