okengine 0.4.3 → 0.5.0

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 (127) hide show
  1. package/package.json +3 -1
  2. package/site/content/docs/ai/index.mdx +24 -0
  3. package/site/content/docs/ai/llms-txt.mdx +3 -0
  4. package/site/content/docs/ai/meta.json +1 -1
  5. package/site/content/docs/console/gates.mdx +46 -8
  6. package/site/content/docs/console/index.mdx +54 -0
  7. package/site/content/docs/console/meta.json +1 -0
  8. package/site/content/docs/elements/gate.mdx +187 -48
  9. package/site/content/docs/elements/index.mdx +45 -0
  10. package/site/content/docs/elements/meta.json +1 -1
  11. package/site/content/docs/get-started/basic-usage.mdx +4 -3
  12. package/site/content/docs/get-started/index.mdx +33 -0
  13. package/site/content/docs/get-started/meta.json +1 -1
  14. package/site/content/docs/index.mdx +9 -31
  15. package/site/content/docs/plugins/anonymous.mdx +95 -0
  16. package/site/content/docs/plugins/compression.mdx +2 -2
  17. package/site/content/docs/plugins/cors.mdx +2 -2
  18. package/site/content/docs/plugins/csrf.mdx +2 -2
  19. package/site/content/docs/plugins/email-otp.mdx +111 -0
  20. package/site/content/docs/plugins/{security-headers.mdx → headers.mdx} +1 -1
  21. package/site/content/docs/plugins/index.mdx +69 -0
  22. package/site/content/docs/plugins/magic-link.mdx +112 -0
  23. package/site/content/docs/plugins/maintenance-mode.mdx +8 -8
  24. package/site/content/docs/plugins/meta.json +10 -1
  25. package/site/content/docs/plugins/passkey.mdx +128 -0
  26. package/site/content/docs/plugins/phone-number.mdx +111 -0
  27. package/site/content/docs/plugins/two-factor.mdx +116 -0
  28. package/site/content/docs/plugins/username.mdx +117 -0
  29. package/site/content/docs/reference/client.mdx +331 -0
  30. package/site/content/docs/reference/fx.mdx +20 -5
  31. package/site/content/docs/reference/index.mdx +45 -0
  32. package/site/content/docs/reference/meta.json +11 -1
  33. package/site/content/docs/reference/plugins.mdx +25 -14
  34. package/src/auth/auth.test.ts +20 -2
  35. package/src/auth/bindings.ts +439 -0
  36. package/src/auth/breach-check.ts +112 -0
  37. package/src/auth/config.ts +288 -0
  38. package/src/auth/cookies.ts +123 -0
  39. package/src/auth/gate-auth.test.ts +379 -0
  40. package/src/auth/identity.ts +190 -0
  41. package/src/auth/index.ts +117 -1
  42. package/src/auth/method-context.ts +33 -0
  43. package/src/auth/operator.ts +27 -1
  44. package/src/auth/password-policy.test.ts +126 -0
  45. package/src/auth/password-policy.ts +77 -0
  46. package/src/auth/plugin.ts +62 -4
  47. package/src/auth/rate.ts +45 -0
  48. package/src/auth/schema.ts +260 -0
  49. package/src/auth/secondary-storage.ts +37 -0
  50. package/src/auth/sessions.ts +58 -1
  51. package/src/auth/tables.ts +4 -0
  52. package/src/auth/verification.ts +78 -0
  53. package/src/cli/dev.test.ts +3 -3
  54. package/src/cli/schema.ts +95 -23
  55. package/src/client/auth.ts +120 -0
  56. package/src/client-react/index.ts +93 -0
  57. package/src/compiler/aot.test.ts +2 -1
  58. package/src/compiler/extract.ts +19 -0
  59. package/src/compiler/response.ts +16 -2
  60. package/src/console/server/app.ts +10 -6
  61. package/src/console/server/auth-rate.test.ts +3 -3
  62. package/src/console/server/bind.ts +12 -1
  63. package/src/console/server/channels.test.ts +1 -1
  64. package/src/console/server/console-gates.ts +14 -0
  65. package/src/console/server/console.test.ts +6 -6
  66. package/src/console/server/flows-invoke.test.ts +2 -2
  67. package/src/console/server/flows.ts +2 -0
  68. package/src/console/server/gates.ts +8 -1
  69. package/src/console/server/operator-db.test.ts +4 -4
  70. package/src/console/server/operator-db.ts +22 -4
  71. package/src/console/server/security.gate.test.ts +3 -3
  72. package/src/console/ui/gates/fixture.ts +4 -0
  73. package/src/console/ui/gates/types.ts +2 -0
  74. package/src/console/ui/shell/client.ts +1 -0
  75. package/src/elements/gate/boot.ts +136 -0
  76. package/src/elements/gate/config.ts +69 -0
  77. package/src/elements/gate/declare.ts +51 -1
  78. package/src/elements/gate/runtime.ts +3 -1
  79. package/src/elements/gate.test.ts +77 -0
  80. package/src/elements/gate.ts +20 -1
  81. package/src/elements/index.ts +8 -0
  82. package/src/index.ts +11 -0
  83. package/src/kernel/app.ts +253 -32
  84. package/src/kernel/boot.test.ts +40 -3
  85. package/src/kernel/boot.ts +8 -0
  86. package/src/kernel/call.test.ts +46 -2
  87. package/src/kernel/edge.test.ts +3 -3
  88. package/src/kernel/flow.test.ts +2 -2
  89. package/src/kernel/fx.test.ts +1 -0
  90. package/src/kernel/fx.ts +60 -0
  91. package/src/kernel/hooks.test.ts +4 -4
  92. package/src/kernel/index.ts +12 -0
  93. package/src/kernel/pipeline.test.ts +12 -8
  94. package/src/kernel/pipeline.ts +23 -4
  95. package/src/kernel/plugin/decorate.test.ts +3 -3
  96. package/src/kernel/plugin/scoping.test.ts +3 -3
  97. package/src/kernel/plugin-elements.test.ts +51 -0
  98. package/src/kernel/plugin-needs.test.ts +83 -0
  99. package/src/kernel/plugin-needs.ts +129 -0
  100. package/src/kernel/plugin.ts +101 -0
  101. package/src/kernel/registry-isolation.test.ts +5 -5
  102. package/src/kernel/registry.ts +102 -3
  103. package/src/manifest/types.ts +2 -0
  104. package/src/plugins/anonymous.ts +58 -0
  105. package/src/plugins/auth/shared.ts +121 -0
  106. package/src/plugins/auth-methods.test.ts +176 -0
  107. package/src/plugins/compression.test.ts +5 -5
  108. package/src/plugins/config-source.test.ts +1 -1
  109. package/src/plugins/cors.test.ts +16 -10
  110. package/src/plugins/csrf.test.ts +1 -1
  111. package/src/plugins/email-otp.ts +161 -0
  112. package/src/plugins/index.ts +31 -0
  113. package/src/plugins/ip-allowlist.test.ts +19 -9
  114. package/src/plugins/magic-link.ts +163 -0
  115. package/src/plugins/maintenance-mode.test.ts +9 -5
  116. package/src/plugins/passkey.ts +216 -0
  117. package/src/plugins/phone-number.ts +149 -0
  118. package/src/plugins/security-headers.test.ts +14 -14
  119. package/src/plugins/two-factor.ts +249 -0
  120. package/src/plugins/username.ts +148 -0
  121. package/src/runs/runs.test.ts +6 -2
  122. package/src/runtime/primitives.ts +37 -4
  123. package/src/runtime/serve.test.ts +3 -2
  124. package/src/runtime/types.ts +25 -2
  125. package/src/test/create-test-app.test.ts +1 -1
  126. package/src/test/create-test-app.ts +4 -1
  127. package/src/test/provisions.integration.test.ts +1 -1
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: "Get Started"
3
+ description: "From the one law to a running app — introduction, why OKE, install, and first flows."
4
+ icon: "Rocket"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Learn the shape once, install on Bun, then write your first Flow from the standard starter.
9
+
10
+ ## Pages
11
+
12
+ <Cards>
13
+ <Card
14
+ title="Introduction"
15
+ description="One law, eight elements, ten exports."
16
+ href="/docs/get-started/introduction"
17
+ />
18
+ <Card
19
+ title="Why OKE"
20
+ description="Six seams every backend maintains by hand."
21
+ href="/docs/get-started/why"
22
+ />
23
+ <Card
24
+ title="Installation"
25
+ description="Scaffold with create-oke and open the Console."
26
+ href="/docs/get-started/installation"
27
+ />
28
+ <Card
29
+ title="Basic Usage"
30
+ description="Health Flow, typed client, Console proof."
31
+ href="/docs/get-started/basic-usage"
32
+ />
33
+ </Cards>
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "title": "Get Started",
3
3
  "icon": "Rocket",
4
- "pages": ["introduction", "why", "installation", "basic-usage"]
4
+ "pages": ["index", "introduction", "why", "installation", "basic-usage"]
5
5
  }
@@ -23,41 +23,19 @@ on(orderPlaced, sendReceipt);
23
23
  <Card
24
24
  title="Get Started"
25
25
  description="One law → install → first flows."
26
- href="/docs/get-started/introduction"
27
- />
28
- <Card
29
- title="Basic Usage"
30
- description="Build from the standard starter."
31
- href="/docs/get-started/basic-usage"
32
- />
33
- <Card
34
- title="Elements"
35
- description="Flow → AI reference, one page each."
36
- href="/docs/elements/flow"
37
- />
38
- <Card
39
- title="Console"
40
- description="Seventeen Manifest-derived panels."
41
- href="/docs/console/overview"
26
+ href="/docs/get-started"
42
27
  />
28
+ <Card title="Elements" description="Flow → AI reference, one page each." href="/docs/elements" />
43
29
  <Card
44
30
  title="Plugins"
45
- description="Official extensions — security headers, CORS, CSRF, compression, maintenance, IP rules."
46
- href="/docs/plugins/security-headers"
47
- />
48
- <Card
49
- title="CLI Reference"
50
- description="`oke` and `create-oke` everyday commands."
51
- href="/docs/reference/cli"
52
- />
53
- <Card
54
- title="Security"
55
- description="Console security posture — Host, Origin, MCP."
56
- href="/docs/reference/security"
31
+ description="Official extensions — security, ops, performance."
32
+ href="/docs/plugins"
57
33
  />
34
+ <Card title="Console" description="Manifest-derived operator panels." href="/docs/console" />
58
35
  <Card
59
- title="AI Resources"
60
- description="AGENTS.md, MCP `:6535`, `/llms.txt`."
61
- href="/docs/ai/mcp"
36
+ title="Reference"
37
+ description="Config, fx, env, errors, CLI, security."
38
+ href="/docs/reference"
62
39
  />
40
+ <Card title="AI Resources" description="MCP, skills, /llms.txt." href="/docs/ai" />
63
41
  </Cards>
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: "Anonymous"
3
+ description: "Official plugin — issue a user-plane session with a random id and no password."
4
+ icon: "UserRoundMinus"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ `anonymous()` creates a throwaway principal: one public Flow returns hybrid session tokens for a
9
+ new random `userId`. Use it for guest carts or try-before-account flows.
10
+
11
+ <Callout title="The one rule">
12
+ Enable `gate.auth`, then `.plug(anonymous())`. Treat the session like any other Bearer principal —
13
+ gates still decide what it may do.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Plug it
22
+
23
+ ```typescript title="src/app.ts"
24
+ import { oke } from "okengine";
25
+ import { anonymous } from "okengine/plugins";
26
+
27
+ export const app = oke({
28
+ name: "shop",
29
+ env: "local",
30
+ gate: { auth: {} },
31
+ }).plug(anonymous());
32
+ ```
33
+
34
+ </Step>
35
+
36
+ <Step>
37
+ ### Sign in anonymously
38
+
39
+ ```typescript
40
+ const { data } = await api.auth.signInAnonymous();
41
+ // data.userId is a fresh UUID; store tokens like any other session
42
+ ```
43
+
44
+ `POST /auth/sign-in/anonymous` — no body.
45
+
46
+ </Step>
47
+
48
+ <Step>
49
+ ### Gate what guests can do
50
+
51
+ Attach real policies to guest-capable Flows (`gate.scope`, custom policies). Anonymous only
52
+ issues a session — it does not grant scopes.
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Options
59
+
60
+ | Option | Type | Default | Meaning |
61
+ | ------------- | -------------- | ---------- | ----------------------------------------------------------- |
62
+ | `secret` | `string` | active\* | HMAC secret (\*from `gate.auth` when plugged after `oke()`) |
63
+ | `sessions` | `SessionStore` | active\* | Session store shared with Gate auth |
64
+ | `now` | `() => number` | `Date.now` | Injectable clock |
65
+ | `emailDomain` | `string` | — | Reserved; unused in v1 |
66
+
67
+ ## Surfaces
68
+
69
+ | Flow | Path | Gate |
70
+ | ---------------------- | ------------------------------ | ---------------------------- |
71
+ | `auth.signInAnonymous` | `POST /auth/sign-in/anonymous` | `gate.public` + sign-in rate |
72
+
73
+ ## Troubleshooting
74
+
75
+ <Accordions>
76
+ <Accordion title="plugin boot failed — needs &quot;auth&quot;">
77
+
78
+ Set `oke({ gate: { auth: { … } } })` before `.plug(anonymous())`.
79
+
80
+ </Accordion>
81
+ </Accordions>
82
+
83
+ ## Learn more
84
+
85
+ - [Gate](/docs/elements/gate) — policies on the new principal
86
+ - [Username](/docs/plugins/username) — upgrade path to a real credential
87
+ - [Plugins](/docs/plugins) — all auth method plugins
88
+
89
+ ## Next
90
+
91
+ <Cards>
92
+ <Card title="Username" description="Username + password." href="/docs/plugins/username" />
93
+ <Card title="Gate" description="Builtin auth and policies." href="/docs/elements/gate" />
94
+ <Card title="Magic link" description="Email link sign-in." href="/docs/plugins/magic-link" />
95
+ </Cards>
@@ -47,9 +47,9 @@ Thresholds and matchers can follow the database like every other official plugin
47
47
 
48
48
  <Cards>
49
49
  <Card
50
- title="Security Headers"
50
+ title="Headers"
51
51
  description="The full secure-headers set on every response."
52
- href="/docs/plugins/security-headers"
52
+ href="/docs/plugins/headers"
53
53
  />
54
54
  <Card
55
55
  title="IP Allowlist"
@@ -86,9 +86,9 @@ See [Plugins → Runtime configuration](/docs/reference/plugins#runtime-configur
86
86
  href="/docs/plugins/csrf"
87
87
  />
88
88
  <Card
89
- title="Security Headers"
89
+ title="Headers"
90
90
  description="The full secure-headers set on every response."
91
- href="/docs/plugins/security-headers"
91
+ href="/docs/plugins/headers"
92
92
  />
93
93
  <Card
94
94
  title="Plugin API"
@@ -89,8 +89,8 @@ See [Plugins → Runtime configuration](/docs/reference/plugins#runtime-configur
89
89
  href="/docs/elements/gate"
90
90
  />
91
91
  <Card
92
- title="Security Headers"
92
+ title="Headers"
93
93
  description="The full secure-headers set on every response."
94
- href="/docs/plugins/security-headers"
94
+ href="/docs/plugins/headers"
95
95
  />
96
96
  </Cards>
@@ -0,0 +1,111 @@
1
+ ---
2
+ title: "Email OTP"
3
+ description: "Official plugin — six-digit email one-time codes to sign in under /auth."
4
+ icon: "MailCheck"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ `emailOtp()` stores a hashed 6-digit code (default 10 minutes, 5 attempts). Verify creates the
9
+ user on first success and returns hybrid session tokens.
10
+
11
+ <Callout title="The one rule">
12
+ Enable `gate.auth`, then `.plug(emailOtp())`. Never log raw OTPs. Channel email delivery is not
13
+ wired yet — use `exposeDevOtp` locally.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Plug it
22
+
23
+ ```typescript title="src/app.ts"
24
+ import { oke } from "okengine";
25
+ import { emailOtp } from "okengine/plugins";
26
+
27
+ export const app = oke({
28
+ name: "shop",
29
+ env: "local",
30
+ gate: { auth: {} },
31
+ }).plug(emailOtp({ exposeDevOtp: true }));
32
+ ```
33
+
34
+ </Step>
35
+
36
+ <Step>
37
+ ### Request a code
38
+
39
+ ```typescript
40
+ const { data } = await api.auth.requestEmailOtp({ email: "ali@example.com" });
41
+ // data.devOtp when exposeDevOtp
42
+ ```
43
+
44
+ `POST /auth/email-otp/request` — prior active codes for that email are invalidated.
45
+
46
+ </Step>
47
+
48
+ <Step>
49
+ ### Verify
50
+
51
+ ```typescript
52
+ const { data } = await api.auth.verifyEmailOtp({
53
+ email: "ali@example.com",
54
+ otp: data!.devOtp!,
55
+ });
56
+ ```
57
+
58
+ `POST /auth/email-otp/verify`. Wrong code increments attempts; after 5 →
59
+ `invalid_credentials`.
60
+
61
+ </Step>
62
+
63
+ </Steps>
64
+
65
+ ## Options
66
+
67
+ | Option | Type | Default | Meaning |
68
+ | --------------- | ------------------- | -------- | --------------------------------------- |
69
+ | `secret` | `string` | active\* | HMAC secret (\*from `gate.auth`) |
70
+ | `sessions` | `SessionStore` | active\* | Session store |
71
+ | `ttlMs` | `number` | 10m | Challenge lifetime |
72
+ | `exposeDevOtp` | `boolean` | `false` | Include raw OTP in the request response |
73
+ | `identities` | `IdentityStore` | new | Email → user map |
74
+ | `verifications` | `VerificationStore` | new | Challenge store |
75
+
76
+ ## Surfaces
77
+
78
+ | Flow | Path | Gate |
79
+ | ---------------------- | ------------------------------ | ------------------------ |
80
+ | `auth.requestEmailOtp` | `POST /auth/email-otp/request` | `gate.public` + otp rate |
81
+ | `auth.verifyEmailOtp` | `POST /auth/email-otp/verify` | `gate.public` + otp rate |
82
+
83
+ ## Troubleshooting
84
+
85
+ <Accordions>
86
+ <Accordion title="No email with the code">
87
+
88
+ v1 does not send mail. Use `exposeDevOtp` in local/test, or send the code via your own Channel
89
+ Flow.
90
+
91
+ </Accordion>
92
+ <Accordion title="AuthFailed after a few tries">
93
+
94
+ Five failed attempts consume the challenge. Request a new OTP.
95
+
96
+ </Accordion>
97
+ </Accordions>
98
+
99
+ ## Learn more
100
+
101
+ - [Magic link](/docs/plugins/magic-link) — link instead of a code
102
+ - [Phone number](/docs/plugins/phone-number) — SMS OTP (E.164)
103
+ - [Gate](/docs/elements/gate) — `gate.auth`
104
+
105
+ ## Next
106
+
107
+ <Cards>
108
+ <Card title="Phone number" description="E.164 SMS OTP." href="/docs/plugins/phone-number" />
109
+ <Card title="Magic link" description="Email link sign-in." href="/docs/plugins/magic-link" />
110
+ <Card title="Two-factor" description="TOTP step-up." href="/docs/plugins/two-factor" />
111
+ </Cards>
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: "Security Headers"
2
+ title: "Headers"
3
3
  description: "Official plugin — the complete secure-headers set on every HTTP response, failures included. Full helmet.js parity with API-first defaults, a CSP builder with report-only mode, and live DB-driven config."
4
4
  icon: "ShieldCheck"
5
5
  source: "src/plugins/security-headers.ts"
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: "Plugins"
3
+ description: "Official okengine/plugins extensions — authentication, security, operations, and performance."
4
+ icon: "Puzzle"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ First-party plugins you `.plug()` onto an app. Each page is one export from `okengine/plugins`.
9
+
10
+ ## Authentication
11
+
12
+ <Cards>
13
+ <Card title="Username" description="Username + password." href="/docs/plugins/username" />
14
+ <Card
15
+ title="Anonymous"
16
+ description="Guest session, no password."
17
+ href="/docs/plugins/anonymous"
18
+ />
19
+ <Card title="Magic link" description="One-time email link." href="/docs/plugins/magic-link" />
20
+ <Card title="Email OTP" description="Six-digit email codes." href="/docs/plugins/email-otp" />
21
+ <Card title="Phone number" description="E.164 SMS OTP." href="/docs/plugins/phone-number" />
22
+ <Card title="Two-factor" description="TOTP enable / verify." href="/docs/plugins/two-factor" />
23
+ <Card title="Passkey" description="WebAuthn-shaped passkeys." href="/docs/plugins/passkey" />
24
+ </Cards>
25
+
26
+ ## Security
27
+
28
+ <Cards>
29
+ <Card
30
+ title="Headers"
31
+ description="Secure headers on every HTTP response."
32
+ href="/docs/plugins/headers"
33
+ />
34
+ <Card
35
+ title="CORS"
36
+ description="Cross-origin rules; closed by default."
37
+ href="/docs/plugins/cors"
38
+ />
39
+ <Card
40
+ title="CSRF"
41
+ description="Fetch-metadata forgery defense, no tokens."
42
+ href="/docs/plugins/csrf"
43
+ />
44
+ <Card
45
+ title="IP Allowlist"
46
+ description="Allow/deny by client IP at the edge."
47
+ href="/docs/plugins/ip-allowlist"
48
+ />
49
+ </Cards>
50
+
51
+ ## Operations
52
+
53
+ <Cards>
54
+ <Card
55
+ title="Maintenance Mode"
56
+ description="Drain HTTP with 503 and Retry-After."
57
+ href="/docs/plugins/maintenance-mode"
58
+ />
59
+ </Cards>
60
+
61
+ ## Performance
62
+
63
+ <Cards>
64
+ <Card
65
+ title="Compression"
66
+ description="gzip responses when the client accepts it."
67
+ href="/docs/plugins/compression"
68
+ />
69
+ </Cards>
@@ -0,0 +1,112 @@
1
+ ---
2
+ title: "Magic link"
3
+ description: "Official plugin — request and verify a one-time email link to sign in under /auth."
4
+ icon: "Link2"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ `magicLink()` issues a hashed, single-use token (default 10 minutes). Verify exchanges it for a
9
+ hybrid session and creates the user on first success.
10
+
11
+ <Callout title="The one rule">
12
+ Enable `gate.auth`, then `.plug(magicLink())`. Tokens are hashed at rest — never log the raw link.
13
+ Channel email delivery is not wired yet; use `exposeDevToken` locally.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Plug it
22
+
23
+ ```typescript title="src/app.ts"
24
+ import { oke } from "okengine";
25
+ import { magicLink } from "okengine/plugins";
26
+
27
+ export const app = oke({
28
+ name: "shop",
29
+ env: "local",
30
+ gate: { auth: {} },
31
+ }).plug(magicLink({ exposeDevToken: true }));
32
+ ```
33
+
34
+ </Step>
35
+
36
+ <Step>
37
+ ### Request a link
38
+
39
+ ```typescript
40
+ const { data } = await api.auth.requestMagicLink({ email: "ali@example.com" });
41
+ // data.ok === true; data.devToken only when exposeDevToken
42
+ ```
43
+
44
+ `POST /auth/magic-link/request`.
45
+
46
+ </Step>
47
+
48
+ <Step>
49
+ ### Verify
50
+
51
+ ```typescript
52
+ const { data } = await api.auth.verifyMagicLink({ token: data!.devToken! });
53
+ // session tokens + userId
54
+ ```
55
+
56
+ `POST /auth/magic-link/verify`. Bad or reused tokens → `AuthFailed` /
57
+ `invalid_credentials`.
58
+
59
+ </Step>
60
+
61
+ </Steps>
62
+
63
+ ## Options
64
+
65
+ | Option | Type | Default | Meaning |
66
+ | ---------------- | ------------------- | -------- | ----------------------------------------- |
67
+ | `secret` | `string` | active\* | HMAC secret (\*from `gate.auth`) |
68
+ | `sessions` | `SessionStore` | active\* | Session store |
69
+ | `ttlMs` | `number` | 10m | Challenge lifetime |
70
+ | `exposeDevToken` | `boolean` | `false` | Include raw token in the request response |
71
+ | `identities` | `IdentityStore` | new | Email → user map |
72
+ | `verifications` | `VerificationStore` | new | Challenge store |
73
+
74
+ ## Surfaces
75
+
76
+ | Flow | Path | Gate |
77
+ | ----------------------- | ------------------------------- | ------------------------ |
78
+ | `auth.requestMagicLink` | `POST /auth/magic-link/request` | `gate.public` + otp rate |
79
+ | `auth.verifyMagicLink` | `POST /auth/magic-link/verify` | `gate.public` + otp rate |
80
+
81
+ **Consequence:** until Channel delivery ships, production apps must send the link themselves
82
+ (or keep `exposeDevToken` off and never log tokens).
83
+
84
+ ## Troubleshooting
85
+
86
+ <Accordions>
87
+ <Accordion title="verify returns invalid_credentials">
88
+
89
+ Token expired (default 10m), already used, or mistyped. Request a new link.
90
+
91
+ </Accordion>
92
+ <Accordion title="No email arrived">
93
+
94
+ v1 does not send mail. Use `exposeDevToken` in local/test, or deliver `devToken` / your own
95
+ link via a Channel Flow you own.
96
+
97
+ </Accordion>
98
+ </Accordions>
99
+
100
+ ## Learn more
101
+
102
+ - [Email OTP](/docs/plugins/email-otp) — numeric code instead of a link
103
+ - [Gate](/docs/elements/gate) — `gate.auth`
104
+ - [Channel](/docs/elements/channel) — when you wire delivery yourself
105
+
106
+ ## Next
107
+
108
+ <Cards>
109
+ <Card title="Email OTP" description="Six-digit email codes." href="/docs/plugins/email-otp" />
110
+ <Card title="Gate" description="Builtin auth and policies." href="/docs/elements/gate" />
111
+ <Card title="Username" description="Password sign-in." href="/docs/plugins/username" />
112
+ </Cards>
@@ -60,12 +60,12 @@ With `MAINTENANCE_MODE=1` in the environment, every HTTP flow answers:
60
60
 
61
61
  ## Notes
62
62
 
63
- | Behavior | Detail |
64
- | ----------------- | ----------------------------------------------------------------------------------- |
65
- | Pipeline position | `onRequest` — flows never parse, authenticate, or execute |
66
- | Still shaped | The 503 flows through `onResponse`, so Security Headers and Compression apply to it |
67
- | Non-HTTP triggers | No-op — clock flows and signal subscribers keep running |
68
- | Infra routes | `/_oke/*` bypass the pipeline entirely and stay up |
63
+ | Behavior | Detail |
64
+ | ----------------- | -------------------------------------------------------------------------- |
65
+ | Pipeline position | `onRequest` — flows never parse, authenticate, or execute |
66
+ | Still shaped | The 503 flows through `onResponse`, so Headers and Compression apply to it |
67
+ | Non-HTTP triggers | No-op — clock flows and signal subscribers keep running |
68
+ | Infra routes | `/_oke/*` bypass the pipeline entirely and stay up |
69
69
 
70
70
  ## Runtime configuration
71
71
 
@@ -93,9 +93,9 @@ See [Plugins → Runtime configuration](/docs/reference/plugins#runtime-configur
93
93
  href="/docs/plugins/ip-allowlist"
94
94
  />
95
95
  <Card
96
- title="Security Headers"
96
+ title="Headers"
97
97
  description="The full secure-headers set on every response."
98
- href="/docs/plugins/security-headers"
98
+ href="/docs/plugins/headers"
99
99
  />
100
100
  <Card title="Plugin API" description="Build your own plugin." href="/docs/reference/plugins" />
101
101
  </Cards>
@@ -2,8 +2,17 @@
2
2
  "title": "Plugins",
3
3
  "icon": "Puzzle",
4
4
  "pages": [
5
+ "index",
6
+ "---Authentication---",
7
+ "username",
8
+ "anonymous",
9
+ "magic-link",
10
+ "email-otp",
11
+ "phone-number",
12
+ "two-factor",
13
+ "passkey",
5
14
  "---Security---",
6
- "security-headers",
15
+ "headers",
7
16
  "cors",
8
17
  "csrf",
9
18
  "ip-allowlist",