@starci/hfs 4.9.11 → 4.10.1

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.
Files changed (222) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +7 -9
  3. package/db/backup-receipt.mjs +10 -47
  4. package/db/drift.mjs +1 -1
  5. package/db/dump.mjs +11 -10
  6. package/db/entity-list.mjs +1 -1
  7. package/db/migrate.mjs +83 -259
  8. package/db/new.mjs +46 -0
  9. package/db/post-cutover.mjs +13 -17
  10. package/db/postgres.mjs +80 -0
  11. package/emit/contracts.mjs +5 -9
  12. package/package.json +1 -1
  13. package/release/gate.mjs +3 -15
  14. package/runtime/knowledge/hfs/canon-pins.yaml +44 -24
  15. package/runtime/knowledge/hfs/design-truths.yaml +1 -1
  16. package/runtime/knowledge/hfs/fe-stack.yaml +4 -11
  17. package/runtime/knowledge/hfs/rules.yaml +179 -157
  18. package/runtime/knowledge/hfs/slots.yaml +185 -172
  19. package/runtime/knowledge/patterns/be/event-bus.yaml +3 -3
  20. package/runtime/knowledge/patterns/be/idempotency.yaml +3 -3
  21. package/runtime/knowledge/patterns/be/jobs.yaml +4 -4
  22. package/runtime/knowledge/patterns/be/projections.yaml +7 -5
  23. package/runtime/knowledge/patterns/be/queues.yaml +8 -8
  24. package/runtime/knowledge/patterns/be/reactors.yaml +2 -2
  25. package/runtime/knowledge/patterns/be/realtime.yaml +6 -6
  26. package/runtime/knowledge/patterns/be/saga.yaml +3 -3
  27. package/runtime/knowledge/patterns/be/webhooks.yaml +1 -1
  28. package/runtime/modules/kernel/command-policy.yaml +1 -1
  29. package/runtime/modules/kernel/failure-codes.yaml +65 -115
  30. package/runtime/modules/schemas/application-stacks.schema.yaml +5 -5
  31. package/runtime/scripts/hfs/architecture/canon-clones.mjs +1 -1
  32. package/runtime/scripts/hfs/architecture/entity-registry.mjs +53 -0
  33. package/runtime/scripts/hfs/architecture/{supabase-be.mjs → identity.mjs} +45 -15
  34. package/runtime/scripts/hfs/architecture/index.mjs +2 -3
  35. package/runtime/scripts/hfs/architecture/{supabase-ast.mjs → jwt-ast.mjs} +2 -103
  36. package/runtime/scripts/hfs/architecture/owners.mjs +11 -0
  37. package/runtime/scripts/hfs/architecture/register-once.mjs +1 -1
  38. package/runtime/scripts/hfs/architecture/schema-owner.mjs +29 -4
  39. package/runtime/scripts/hfs/architecture/server-action.mjs +3 -4
  40. package/runtime/scripts/hfs/architecture/side-boundary.mjs +1 -1
  41. package/runtime/scripts/hfs/architecture/{supabase-keys.mjs → sql-keys.mjs} +1 -1
  42. package/runtime/scripts/hfs/architecture/sql-owner.mjs +25 -27
  43. package/runtime/scripts/hfs/architecture/tiers.mjs +14 -3
  44. package/runtime/scripts/hfs/architecture/transport-owner.mjs +7 -3
  45. package/runtime/scripts/hfs/check.mjs +6 -6
  46. package/runtime/scripts/hfs/coverage-scope.mjs +1 -1
  47. package/runtime/scripts/hfs/db-baseline-verb.mjs +48 -30
  48. package/runtime/scripts/hfs/db-plan-verb.mjs +17 -106
  49. package/runtime/scripts/hfs/db-restamp-verb.mjs +11 -10
  50. package/runtime/scripts/hfs/declaration-shape.mjs +15 -18
  51. package/runtime/scripts/hfs/manifest-shape.mjs +9 -5
  52. package/runtime/scripts/hfs/rule-params-shape.mjs +4 -1
  53. package/runtime/scripts/hfs/rules/a15-findings.mjs +1 -1
  54. package/runtime/scripts/hfs/rules/cli.mjs +1 -1
  55. package/runtime/scripts/hfs/rules/database-access.mjs +8 -74
  56. package/runtime/scripts/hfs/rules/database-baseline.mjs +3 -3
  57. package/runtime/scripts/hfs/rules/database-config.mjs +6 -214
  58. package/runtime/scripts/hfs/rules/database-constants.mjs +8 -10
  59. package/runtime/scripts/hfs/rules/database-migrations.mjs +3 -3
  60. package/runtime/scripts/hfs/rules/database-queues.mjs +4 -5
  61. package/runtime/scripts/hfs/rules/database-sql.mjs +1 -1
  62. package/runtime/scripts/hfs/rules/database.mjs +36 -39
  63. package/runtime/scripts/hfs/rules/edition.mjs +1 -1
  64. package/runtime/scripts/hfs/rules/{supabase-secrets.mjs → lite-secrets.mjs} +6 -6
  65. package/runtime/scripts/hfs/rules/script-hygiene.mjs +1 -10
  66. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +5 -4
  67. package/runtime/scripts/hfs/rules/stacks-release.mjs +3 -2
  68. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +2 -2
  69. package/runtime/scripts/hfs/rules/stacks.mjs +1 -1
  70. package/runtime/scripts/hfs/slot-app-view.mjs +1 -1
  71. package/runtime/scripts/hfs/slots.mjs +8 -2
  72. package/runtime/scripts/hfs/sql/pg-parse.mjs +2 -2
  73. package/runtime/scripts/lib/secret-patterns.mjs +2 -2
  74. package/runtime/scripts/lib/swarm-stack.mjs +7 -4
  75. package/scaffold/add-app.mjs +2 -10
  76. package/scaffold/add-cli-lite.mjs +6 -6
  77. package/scaffold/add-compose.mjs +1 -1
  78. package/scaffold/add-inbox-lite.mjs +4 -8
  79. package/scaffold/add-plan.mjs +1 -1
  80. package/scaffold/add-queue-lite.mjs +16 -24
  81. package/scaffold/add-table.mjs +34 -26
  82. package/scaffold/add.mjs +2 -2
  83. package/scaffold/app.mjs +19 -86
  84. package/scaffold/lite-exports.mjs +1 -1
  85. package/src/main.mjs +19 -20
  86. package/stack/target-binding.mjs +0 -60
  87. package/stack/urgent-floor.mjs +2 -2
  88. package/sync/index.mjs +32 -8
  89. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -17
  90. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +6 -8
  91. package/templates/app/codegen-lite/scripts/codegen.mjs +2 -39
  92. package/templates/app/db-bootstrap/db/bootstrap.sql +139 -0
  93. package/templates/app/gitignore-lite +0 -3
  94. package/templates/app/package-scripts/db.json +9 -0
  95. package/templates/app/package-scripts/package.json +0 -1
  96. package/templates/app/package-scripts-lite/package.json +1 -1
  97. package/templates/app/skeleton/.starcistacks/dev/README.md +1 -1
  98. package/templates/app/skeleton/.starcistacks/production/README.md +1 -1
  99. package/templates/app/skeleton/README.md +1 -1
  100. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +84 -19
  101. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +5 -5
  102. package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +1 -1
  103. package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/recovery/restore-proof.md +1 -1
  104. package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +69 -6
  105. package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +18 -7
  106. package/templates/app/skeleton-lite/.starcistacks/production/README.md +6 -6
  107. package/templates/app/skeleton-lite/.starcistacks/production/environment.json +1 -1
  108. package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/recovery/restore-proof.md +2 -2
  109. package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +69 -6
  110. package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +17 -9
  111. package/templates/app/skeleton-lite/README.md +11 -11
  112. package/templates/app/skeleton-lite/{supabase → db}/migrations/__timestamp___baseline.sql +21 -1
  113. package/templates/app/tool-config-lite/prettierignore +0 -1
  114. package/templates/be/inbox/database-client.spec.ts.tpl +9 -5
  115. package/templates/be/inbox/database-client.ts.tpl +13 -4
  116. package/templates/be/inbox/platform/client-operation-outcomes.sql.tpl +47 -0
  117. package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +3 -1
  118. package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +2 -2
  119. package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +6 -1
  120. package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +39 -7
  121. package/templates/be/inbox/platform/migration.sql.tpl +22 -0
  122. package/templates/be/inbox/service.spec.ts.tpl +2 -2
  123. package/templates/be/inbox/service.ts.tpl +1 -2
  124. package/templates/be/patterns/jobs/platform-lite/job-claim.service.spec.ts.tpl +156 -0
  125. package/templates/be/patterns/jobs/platform-lite/job-claim.service.ts.tpl +114 -0
  126. package/templates/be/patterns/jobs/platform-lite/jobs.sql.tpl +51 -0
  127. package/templates/be/patterns/queues/platform-lite/queue-outbox.service.spec.ts.tpl +62 -0
  128. package/templates/be/patterns/queues/platform-lite/queue-outbox.service.ts.tpl +20 -0
  129. package/templates/be/patterns/queues/platform-lite/queue-outbox.sql.tpl +35 -0
  130. package/templates/be/patterns/queues/platform-lite/queue-relay.service.spec.ts.tpl +4 -1
  131. package/templates/be/patterns/queues/platform-lite/queue-relay.service.ts.tpl +16 -5
  132. package/templates/be/patterns/realtime/channel.gateway.spec.ts.tpl +8 -8
  133. package/templates/be/patterns/realtime/channel.websocket.module.ts.tpl +3 -3
  134. package/templates/be/patterns/realtime/channel.websocket.options.ts.tpl +2 -2
  135. package/templates/be/skeleton-lite/apps/api/Dockerfile +0 -1
  136. package/templates/be/skeleton-lite/apps/api/src/api.env.ts +9 -5
  137. package/templates/be/skeleton-lite/apps/api/src/api.options.ts +7 -4
  138. package/templates/be/skeleton-lite/apps/api/src/app.module.ts +4 -4
  139. package/templates/be/skeleton-lite/apps/api/src/compose/domain.ts +3 -3
  140. package/templates/be/skeleton-lite/apps/api/src/compose/integrations.ts +9 -13
  141. package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +4 -2
  142. package/templates/be/skeleton-lite/apps/cli/src/cli.env.ts +2 -2
  143. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +3 -2
  144. package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.spec.ts +4 -4
  145. package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +3 -3
  146. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +1 -1
  147. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +6 -6
  148. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +3 -3
  149. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/index.ts +4 -0
  150. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.client.spec.ts +22 -0
  151. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.client.ts +25 -0
  152. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.config.ts +12 -0
  153. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.decorators.ts +9 -0
  154. package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.options.ts +35 -0
  155. package/templates/be/skeleton-lite/src/modules/integrations/passport/errors/passport.error.ts +22 -0
  156. package/templates/be/skeleton-lite/src/modules/integrations/passport/index.ts +12 -0
  157. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +23 -0
  158. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +29 -0
  159. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.decorators.ts +22 -0
  160. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +63 -0
  161. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.password.ts +11 -0
  162. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.tokens.spec.ts +32 -0
  163. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.tokens.ts +69 -0
  164. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +37 -0
  165. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/local.strategy.ts +36 -0
  166. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +59 -0
  167. package/templates/be/skeleton-lite/src/modules/platform/database/database.functions.ts +24 -0
  168. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +2 -1
  169. package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +4 -2
  170. package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +19 -6
  171. package/templates/be/skeleton-lite/src/modules/platform/database/entities.ts +7 -0
  172. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +1 -0
  173. package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +1 -1
  174. package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +2 -2
  175. package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +2 -2
  176. package/templates/be/skeleton-lite/src/tests/fixtures/builders/api.builder.ts +18 -5
  177. package/templates/be/skeleton-lite/src/tests/fixtures/builders/cli.builder.ts +1 -1
  178. package/templates/be/table/entities.index.ts.tpl +4 -0
  179. package/templates/be/table/entity.ts.tpl +21 -0
  180. package/templates/be/table/index.ts.tpl +1 -0
  181. package/templates/be/table/module.ts.tpl +1 -1
  182. package/templates/be/table/service.api.ts.tpl +10 -11
  183. package/templates/be/table/service.ts.tpl +5 -6
  184. package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/auth-door.ts +30 -0
  185. package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/client.ts +46 -14
  186. package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/token-store.ts +31 -0
  187. package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +2 -5
  188. package/db/local-migrate.mjs +0 -194
  189. package/db/reset.mjs +0 -125
  190. package/emit/db-types.mjs +0 -271
  191. package/runtime/scripts/api/supabase/database-dump.mjs +0 -5
  192. package/runtime/scripts/api/supabase/database-push.mjs +0 -5
  193. package/runtime/scripts/api/supabase/database-query.mjs +0 -5
  194. package/runtime/scripts/api/supabase/lib.mjs +0 -55
  195. package/runtime/scripts/api/supabase/migration-repair.mjs +0 -5
  196. package/runtime/scripts/hfs/architecture/supabase-tables.mjs +0 -50
  197. package/runtime/scripts/hfs/architecture/supabase.mjs +0 -226
  198. package/scaffold/supabase-ports.mjs +0 -26
  199. package/templates/app/package-scripts/supabase.json +0 -7
  200. package/templates/app/skeleton-lite/supabase/config.toml +0 -48
  201. package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +0 -5
  202. package/templates/be/inbox/platform/inbox/persistence/inbox.rows.ts.tpl +0 -33
  203. package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +0 -33
  204. package/templates/be/inbox/sql.ts.tpl +0 -16
  205. package/templates/be/patterns/jobs/platform-lite/persistence.jobs.sql.ts.tpl +0 -33
  206. package/templates/be/patterns/queues/platform-lite/persistence.queue.sql.ts.tpl +0 -12
  207. package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +0 -16
  208. package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +0 -6
  209. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.spec.ts +0 -27
  210. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +0 -24
  211. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +0 -8
  212. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +0 -17
  213. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +0 -32
  214. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +0 -24
  215. package/templates/be/table/rows.ts.tpl +0 -4
  216. package/templates/be/table/sql.api.ts.tpl +0 -7
  217. package/templates/be/table/sql.ts.tpl +0 -4
  218. package/templates/fe/auth/supabase-client.ts.tpl +0 -38
  219. package/templates/fe/skeleton/apps/__app__/src/app/auth/callback/route.ts +0 -11
  220. package/templates/fe/skeleton/apps/__app__/src/modules/auth/pkce-client.ts +0 -18
  221. package/templates/fe/skeleton/apps/__app__/src/modules/auth/server.ts +0 -19
  222. /package/templates/app/skeleton-lite/{supabase → db}/seed.sql +0 -0
@@ -1,8 +0,0 @@
1
- import type { EnvSource } from "@modules/platform/config"
2
- import type { SupabaseOptions } from "./supabase.options"
3
-
4
- /** Reads Supabase configuration with no credential or localhost defaults. */
5
- export const parseSupabaseConfig = (env: EnvSource): SupabaseOptions => ({
6
- url: env.url("SUPABASE_URL"),
7
- serviceRoleKey: env.secret("SUPABASE_SERVICE_ROLE_KEY"),
8
- })
@@ -1,17 +0,0 @@
1
- import { injector } from "@modules/platform/composition"
2
- import type { TypedParameterDecorator } from "@modules/platform/composition"
3
- import type { SupabaseAdminClient } from "./supabase.client"
4
- import type { VerifySupabaseAccessToken } from "./supabase.options"
5
-
6
- /** Token of the integration's Auth and Storage administrator. */
7
- export const SUPABASE_ADMIN_CLIENT: unique symbol = Symbol("integrations.supabase.admin-client")
8
- /** Token of the cryptographic Supabase access-token verifier. */
9
- export const SUPABASE_ACCESS_TOKEN_VERIFIER: unique symbol = Symbol("integrations.supabase.access-token-verifier")
10
-
11
- /** Injects the Auth and Storage administrator. Parameter type: SupabaseAdminClient. */
12
- export const InjectSupabaseAdminClient = (): TypedParameterDecorator<SupabaseAdminClient> =>
13
- injector<SupabaseAdminClient>(SUPABASE_ADMIN_CLIENT)
14
-
15
- /** Injects the access-token verifier. Parameter type: VerifySupabaseAccessToken. */
16
- export const InjectSupabaseAccessTokenVerifier = (): TypedParameterDecorator<VerifySupabaseAccessToken> =>
17
- injector<VerifySupabaseAccessToken>(SUPABASE_ACCESS_TOKEN_VERIFIER)
@@ -1,32 +0,0 @@
1
- import { createRemoteJWKSet, jwtVerify } from "jose"
2
- import { ok, refused } from "@modules/platform/primitives"
3
- import { SupabaseErrorCode } from "./errors/supabase.error"
4
- import type { SupabaseOptions, SupabasePrincipal, VerifySupabaseAccessToken } from "./supabase.options"
5
-
6
- const AUDIENCE = "authenticated"
7
-
8
- /** Creates the verifier for this project's remote JWKS, exact issuer, authenticated audience and pinned algorithm. */
9
- export const createSupabaseAccessTokenVerifier = (options: SupabaseOptions): VerifySupabaseAccessToken => {
10
- const issuer = `${options.url.replace(/\/$/, "")}/auth/v1`
11
- const keys = createRemoteJWKSet(new URL(`${issuer}/.well-known/jwks.json`))
12
- return async (token) => {
13
- try {
14
- const { payload } = await jwtVerify(token, keys, {
15
- algorithms: ["ES256"],
16
- audience: AUDIENCE,
17
- issuer,
18
- })
19
- if (typeof payload.sub !== "string" || typeof payload.exp !== "number" || payload.role !== AUDIENCE) {
20
- return refused(SupabaseErrorCode.AccessTokenInvalid)
21
- }
22
- const principal: SupabasePrincipal = {
23
- id: payload.sub,
24
- role: AUDIENCE,
25
- ...(typeof payload.email === "string" ? { email: payload.email } : {}),
26
- }
27
- return ok(principal)
28
- } catch (cause) {
29
- return refused(SupabaseErrorCode.AccessTokenInvalid, { cause: String(cause) })
30
- }
31
- }
32
- }
@@ -1,24 +0,0 @@
1
- import type { Secret } from "@modules/platform/config"
2
- import type { Outcome } from "@modules/platform/primitives"
3
- import type { SupabaseErrorCode } from "./errors/supabase.error"
4
-
5
- /** The verified identity claims admitted from a Supabase access token. */
6
- export interface SupabasePrincipal {
7
- /** The Auth user identifier from the verified `sub` claim. */
8
- readonly id: string
9
- /** The verified email claim when the provider issued one. */
10
- readonly email?: string
11
- /** Supabase's authenticated role, required by the verifier. */
12
- readonly role: "authenticated"
13
- }
14
-
15
- /** Verifies one bearer token and returns only claims that passed every cryptographic and semantic check. */
16
- export type VerifySupabaseAccessToken = (token: string) => Promise<Outcome<SupabasePrincipal, SupabaseErrorCode>>
17
-
18
- /** Supabase configuration parsed once at API boot. */
19
- export interface SupabaseOptions {
20
- /** The project origin, used for Auth, Storage, issuer and JWKS endpoints. */
21
- readonly url: string
22
- /** The service-role credential, held only by the back-end integration. */
23
- readonly serviceRoleKey: Secret
24
- }
@@ -1,4 +0,0 @@
1
- import type { Database } from "../../../../../../supabase/types/database.types"
2
-
3
- /** One generated row of public.{{table}}. */
4
- export type {{Name}}Row = Database["public"]["Tables"]["{{table}}"]["Row"]
@@ -1,7 +0,0 @@
1
- import { sql } from "@modules/platform/database"
2
-
3
- /** Reads one public.{{table}} row by id and owner through a branded SQL statement. */
4
- export const FIND_{{upper}} = sql`SELECT id FROM public.{{tableSql}} WHERE id = $1 AND owner_id = $2 LIMIT 1`
5
-
6
- /** Inserts one public.{{table}} row owned by the principal and returns its id. */
7
- export const INSERT_{{upper}} = sql`INSERT INTO public.{{tableSql}} (owner_id) VALUES ($1) RETURNING id`
@@ -1,4 +0,0 @@
1
- import { sql } from "@modules/platform/database"
2
-
3
- /** Reads one public.{{table}} row by id and owner through a branded SQL statement. */
4
- export const FIND_{{upper}} = sql`SELECT id FROM public.{{tableSql}} WHERE id = $1 AND owner_id = $2 LIMIT 1`
@@ -1,38 +0,0 @@
1
- const sessionOf = (session: Session | null): AuthSession | undefined =>
2
- session === null
3
- ? undefined
4
- : { userId: session.user.id, ...(session.user.email === undefined ? {} : { email: session.user.email }) }
5
-
6
- /** A Supabase Auth error as the provider reports it: its HTTP status, its code and its message. */
7
- type ProviderError = {
8
- readonly status: number | undefined
9
- readonly code: string | undefined
10
- readonly message: string
11
- }
12
-
13
- /** The failure kind of a Supabase Auth error: refused credentials, rejected input, or the provider unavailable. */
14
- const kindOf = (status: number | undefined): string => {
15
- if (status === 400 || status === 401 || status === 403) return "refused"
16
- return status === 422 ? "invalid" : "unavailable"
17
- }
18
-
19
- /** The failure of a Supabase Auth call, or undefined when it succeeded. */
20
- const failureOf = (error: ProviderError | null): AuthFailure | undefined =>
21
- error === null
22
- ? undefined
23
- : { code: error.code ?? String(error.status ?? "auth"), kind: kindOf(error.status), message: error.message }
24
-
25
- /** The Supabase Auth adapter shared by browser and cookie-backed PKCE flows. */
26
- export const authClient: AuthClient = {
27
- session: async () => sessionOf((await authOf().getSession()).data.session),
28
- accessToken: async () => (await authOf().getSession()).data.session?.access_token,
29
- refreshAccessToken: async () => (await authOf().refreshSession()).data.session?.access_token,
30
- signInWithPassword: async (email, password) =>
31
- failureOf((await authOf().signInWithPassword({ email, password })).error),
32
- signOut: async () => failureOf((await authOf().signOut()).error),
33
- // Supabase reports INITIAL_SESSION on subscribe, then every change: the subscription alone keeps the session current.
34
- onChange: (listener) => {
35
- const { data } = authOf().onAuthStateChange((_event, session) => listener(sessionOf(session)))
36
- return () => data.subscription.unsubscribe()
37
- },
38
- }
@@ -1,11 +0,0 @@
1
- import { NextResponse } from "next/server"
2
- import { exchangeAuthCode } from "@/modules/auth/server"
3
- import { APP_ROUTES } from "@/modules/routes"
4
-
5
- /** The opt-in Supabase PKCE callback only exchanges the code and redirects home. */
6
- export const GET = async (request: Request): Promise<NextResponse> => {
7
- const url = new URL(request.url)
8
- const code = url.searchParams.get("code")
9
- if (code) await exchangeAuthCode(code)
10
- return NextResponse.redirect(new URL(APP_ROUTES.home, url.origin))
11
- }
@@ -1,18 +0,0 @@
1
- import { createBrowserClient } from "@supabase/ssr"
2
- import type { Session, SupabaseClient } from "@supabase/supabase-js"
3
- import { supabaseAnonKey, supabaseUrl } from "@/modules/config"
4
- import type { AuthClient, AuthFailure, AuthSession } from "./contracts"
5
-
6
- let client: SupabaseClient | undefined
7
-
8
- /**
9
- * The cookie-backed browser client of the opt-in server PKCE flow, used for Supabase Auth only.
10
- * The callback exchanges the code; this client shares its verifier and session cookies. It never calls `.from()`, `.rpc()` or storage:
11
- * data goes through modules/api to the back end, which verifies the access token.
12
- */
13
- const supabase = (): SupabaseClient =>
14
- (client ??= createBrowserClient(supabaseUrl(), supabaseAnonKey(), {
15
- auth: { flowType: "pkce", detectSessionInUrl: false, persistSession: true, autoRefreshToken: true },
16
- }))
17
-
18
- // {{> fe/auth/supabase-client.ts.tpl}}
@@ -1,19 +0,0 @@
1
- import "server-only"
2
- import { createServerClient } from "@supabase/ssr"
3
- import { cookies } from "next/headers"
4
- import { supabaseAnonKey, supabaseUrl } from "@/modules/config"
5
-
6
- /** The server auth owner reads the PKCE verifier and persists the exchanged session in cookies. */
7
- export const exchangeAuthCode = async (code: string): Promise<void> => {
8
- const cookieStore = await cookies()
9
- const client = createServerClient(supabaseUrl(), supabaseAnonKey(), {
10
- cookies: {
11
- getAll: () => cookieStore.getAll(),
12
- setAll: (values) => {
13
- for (const { name, value, options } of values) cookieStore.set(name, value, options)
14
- },
15
- },
16
- })
17
- const { error } = await client.auth.exchangeCodeForSession(code)
18
- if (error) throw error
19
- }