@byline/cli 6.7.1 → 6.8.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=preflight-runtime.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight-runtime.test.d.ts","sourceRoot":"","sources":["../../src/phases/preflight-runtime.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { afterEach, describe, expect, it, vi } from 'vitest';
3
+ import { createTestContext } from '../test-helpers.js';
4
+ import { preflightPhase } from './preflight.js';
5
+ const originalNode = Object.getOwnPropertyDescriptor(process.versions, 'node');
6
+ const roots = [];
7
+ afterEach(() => {
8
+ Object.defineProperty(process.versions, 'node', originalNode);
9
+ for (const root of roots.splice(0))
10
+ rmSync(root, { recursive: true, force: true });
11
+ });
12
+ function context(version) {
13
+ Object.defineProperty(process.versions, 'node', { ...originalNode, value: version });
14
+ const ctx = createTestContext({ pm: 'pnpm' });
15
+ roots.push(ctx.cwd);
16
+ mkdirSync(ctx.resolve('.git'));
17
+ writeFileSync(ctx.resolve('package.json'), '{"name":"runtime-fixture"}\n');
18
+ return ctx;
19
+ }
20
+ describe('CLI minimum Node runtime', () => {
21
+ it.each([
22
+ '18.20.2',
23
+ '20.9.0',
24
+ '20.20.0',
25
+ '21.7.3',
26
+ '22.0.0',
27
+ '22.11.9',
28
+ '22.12.0',
29
+ '22.22.0',
30
+ '22.22.1',
31
+ ])('blocks Node %s before installation work', async (version) => {
32
+ const ctx = context(version);
33
+ const error = vi.spyOn(ctx.logger, 'error');
34
+ expect(await preflightPhase.apply(await preflightPhase.plan(ctx), ctx)).toEqual({
35
+ state: 'blocked',
36
+ });
37
+ expect(error).toHaveBeenCalledWith(`Node 22.22.2+ required (found ${version})`);
38
+ error.mockRestore();
39
+ });
40
+ it.each(['22.22.2', '22.23.0', '24.18.0'])('accepts Node %s', async (version) => {
41
+ const ctx = context(version);
42
+ expect(await preflightPhase.apply(await preflightPhase.plan(ctx), ctx)).toEqual({
43
+ state: 'done',
44
+ });
45
+ });
46
+ it('rechecks a previously completed preflight after a runtime downgrade', async () => {
47
+ const ctx = context('22.22.1');
48
+ ctx.state.markPhaseComplete('preflight');
49
+ expect(await preflightPhase.detect(ctx)).toBe('pending');
50
+ expect((await preflightPhase.apply(await preflightPhase.plan(ctx), ctx)).state).toBe('blocked');
51
+ });
52
+ });
53
+ //# sourceMappingURL=preflight-runtime.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight-runtime.test.js","sourceRoot":"","sources":["../../src/phases/preflight-runtime.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/phases/preflight.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExD,eAAO,MAAM,cAAc,EAAE,KA2C5B,CAAA;AAoDD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA2BhE"}
1
+ {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/phases/preflight.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExD,eAAO,MAAM,cAAc,EAAE,KA0C5B,CAAA;AAwDD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA2BhE"}
@@ -1,12 +1,13 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
+ import { gte } from 'semver';
3
4
  import { ancestors, resolveWorkspaceOwnership, validateWorkspacePackageManager, workspaceManagerConstraint, } from '../lib/workspace-root.js';
4
5
  export const preflightPhase = {
5
6
  id: 'preflight',
6
7
  title: 'Preflight — environment checks',
7
8
  defaultMode: 'auto',
8
9
  async detect(ctx) {
9
- if (!ctx.state.isComplete('preflight'))
10
+ if (!supportsNodeRuntime() || !ctx.state.isComplete('preflight'))
10
11
  return 'pending';
11
12
  const selected = ctx.cliFlags.pm ?? ctx.state.get().answers.pm;
12
13
  const constraint = workspaceManagerConstraint(ctx.cwd);
@@ -20,9 +21,8 @@ export const preflightPhase = {
20
21
  return { writes: [], commands: [], notes: ['check Node version, git repo, package manager'] };
21
22
  },
22
23
  async apply(_plan, ctx) {
23
- const major = Number(process.versions.node.split('.')[0]);
24
- if (major < 20) {
25
- ctx.logger.error(`Node 20.9+ required (found ${process.versions.node})`);
24
+ if (!supportsNodeRuntime()) {
25
+ ctx.logger.error(`Node 22.22.2+ required (found ${process.versions.node})`);
26
26
  return { state: 'blocked' };
27
27
  }
28
28
  if (!existsSync(ctx.resolve('.git'))) {
@@ -43,6 +43,9 @@ export const preflightPhase = {
43
43
  return { state: 'done' };
44
44
  },
45
45
  };
46
+ function supportsNodeRuntime() {
47
+ return gte(process.versions.node, '22.22.2');
48
+ }
46
49
  async function resolvePackageManager(ctx) {
47
50
  const fromFlag = ctx.cliFlags.pm;
48
51
  const persisted = ctx.state.get().answers.pm;
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/phases/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EACL,SAAS,EACT,yBAAyB,EACzB,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA;AAIjC,MAAM,CAAC,MAAM,cAAc,GAAU;IACnC,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,gCAAgC;IACvC,WAAW,EAAE,MAAM;IAEnB,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,OAAO,SAAS,CAAA;QACxD,MAAM,QAAQ,GAAI,GAAG,CAAC,QAAQ,CAAC,EAAiC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAA;QAC9F,MAAM,UAAU,GAAG,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACtD,MAAM,QAAQ,GAAG,QAAQ,IAAI,UAAU,CAAC,OAAO,CAAA;QAC/C,IAAI,CAAC,QAAQ,IAAI,CAAC,+BAA+B,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC5F,GAAG,CAAC,EAAE,GAAG,QAAQ,CAAA;QACjB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAI;QACb,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,+CAA+C,CAAC,EAAE,CAAA;IAC/F,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACzD,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAA;YACxE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QAC7B,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAA;YACrF,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACpC,OAAO,EAAE,uBAAuB;gBAChC,YAAY,EAAE,KAAK;aACpB,CAAC,CAAA;YACF,IAAI,CAAC,EAAE;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QACtC,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAA;QAC3C,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QACpC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAA;QACX,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAA;QAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IAC1B,CAAC;CACF,CAAA;AAED,KAAK,UAAU,qBAAqB,CAAC,GAAY;IAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAgC,CAAA;IAC9D,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAA;IAC5C,MAAM,UAAU,GAAG,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACtD,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,MAAM,iDAAiD,CAAC,CAAA;QACvF,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,QAAQ,IAAI,SAAS,CAAA;QACtC,IAAI,QAAQ,IAAI,QAAQ,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,yBAAyB,UAAU,CAAC,OAAO,cAAc,UAAU,CAAC,OAAO,EAAE,CAC9E,CAAA;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2CAA2C,UAAU,CAAC,OAAO,EAAE,CAAC,CAAA;QAChF,OAAO,UAAU,CAAC,OAAO,CAAA;IAC3B,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAA;QACzC,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,SAAS,EAAE,CAAC,CAAA;QAC1E,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,SAAS,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;QACjD,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,mFAAmF,CACpF,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9C,IAAI,GAAG,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAA;IAE5B,uEAAuE;IACvE,uEAAuE;IACvE,uCAAuC;IACvC,MAAM,MAAM,GAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAA;IACjG,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAiB;QACzC,OAAO,EAAE,qCAAqC;QAC9C,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE;YACtD,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;SAC/C;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,UAAU,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAA;IAClD,IAAI,UAAU,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAC5D,IAAI,UAAU,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC,OAAO,CAAA;IACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAA;IAChD,MAAM,mBAAmB,GACvB,SAAS,CAAC,IAAI,KAAK,YAAY;QAC7B,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;QAClB,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACzE,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;QAC/C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAgC,CAAA;YACpF,IAAI,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAA;YACzD,IAAI,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAA;YACzD,IAAI,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YACvD,IAAI,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;QACzD,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;YAAE,OAAO,MAAM,CAAA;QACrE,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;YAAE,OAAO,MAAM,CAAA;QAChE,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YACxF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAAE,OAAO,MAAM,CAAA;QAC3D,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;YAAE,OAAO,KAAK,CAAA;IACpE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/phases/preflight.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import { type AdminStore, registerAdminAbilities } from '@byline/admin'
17
- import { createPasswordSignInLimiter, JwtSessionProvider } from '@byline/admin/auth'
17
+ import { createAuthMaintenanceTasks, createPasswordSignInLimiter, createPasskeyRequestLimiter, JwtSessionProvider } from '@byline/admin/auth'
18
18
  import { getRequestIP } from '@tanstack/react-start/server'
19
19
  import { createClientIpResolver } from '@byline/host-tanstack-start/integrations/client-ip'
20
20
  import { getAdminBylineClient } from '@byline/client/server'
@@ -71,7 +71,29 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
71
71
 
72
72
  const signInLimiter = createPasswordSignInLimiter(adminStore.signInRateLimits, signingSecret)
73
73
 
74
+ // Passkeys remain disabled until explicit site trust is configured. Never infer
75
+ // relying-party identity or origins from request headers.
76
+ const passkeys = [process.env.BYLINE_PASSKEY_RP_ID, process.env.BYLINE_PASSKEY_RP_NAME,
77
+ process.env.BYLINE_PASSKEY_ORIGINS, process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST]
78
+ .some((value) => value !== undefined) ? {
79
+ rpId: process.env.BYLINE_PASSKEY_RP_ID ?? '',
80
+ rpName: process.env.BYLINE_PASSKEY_RP_NAME ?? '',
81
+ origins: process.env.BYLINE_PASSKEY_ORIGINS?.split(',').map((origin) => origin.trim()) ?? [],
82
+ allowInsecureLocalhost: process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST === 'true',
83
+ } : undefined
84
+ const resolveClientIp = createClientIpResolver({
85
+ // Opt in only when the proxy overwrites this header and direct access is blocked.
86
+ trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
87
+ resolvePeerIp: () => getRequestIP() ??
88
+ (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
89
+ })
90
+ const passkeyRequests = passkeys ? {
91
+ limiter: createPasskeyRequestLimiter(adminStore.signInRateLimits, signingSecret),
92
+ resolveClientIp,
93
+ } : undefined
94
+
74
95
  const sessionProvider = new JwtSessionProvider({
96
+ passkeys,
75
97
  store: adminStore,
76
98
  signingSecret,
77
99
  })
@@ -90,15 +112,12 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
90
112
  baseUrl: '/uploads',
91
113
  }),
92
114
  sessionProvider,
93
- recurringTasks: [signInLimiter.cleanupTask],
115
+ passkeys,
116
+ passkeyRequests,
117
+ recurringTasks: [...createAuthMaintenanceTasks(adminStore), signInLimiter.cleanupTask],
94
118
  passwordSignIn: {
95
119
  limiter: signInLimiter,
96
- resolveClientIp: createClientIpResolver({
97
- // Opt in only when the proxy overwrites this header and direct access is blocked.
98
- trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
99
- resolvePeerIp: () => getRequestIP() ??
100
- (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
101
- }),
120
+ resolveClientIp,
102
121
  },
103
122
  fields: {
104
123
  richText: {
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import { type AdminStore, registerAdminAbilities } from '@byline/admin'
14
- import { createPasswordSignInLimiter, JwtSessionProvider } from '@byline/admin/auth'
14
+ import { createAuthMaintenanceTasks, createPasswordSignInLimiter, createPasskeyRequestLimiter, JwtSessionProvider } from '@byline/admin/auth'
15
15
  import { getRequestIP } from '@tanstack/react-start/server'
16
16
  import { createClientIpResolver } from '@byline/host-tanstack-start/integrations/client-ip'
17
17
  import { getAdminBylineClient } from '@byline/client/server'
@@ -79,7 +79,29 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
79
79
 
80
80
  const signInLimiter = createPasswordSignInLimiter(adminStore.signInRateLimits, signingSecret)
81
81
 
82
+ // Passkeys remain disabled until explicit site trust is configured. Never infer
83
+ // relying-party identity or origins from request headers.
84
+ const passkeys = [process.env.BYLINE_PASSKEY_RP_ID, process.env.BYLINE_PASSKEY_RP_NAME,
85
+ process.env.BYLINE_PASSKEY_ORIGINS, process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST]
86
+ .some((value) => value !== undefined) ? {
87
+ rpId: process.env.BYLINE_PASSKEY_RP_ID ?? '',
88
+ rpName: process.env.BYLINE_PASSKEY_RP_NAME ?? '',
89
+ origins: process.env.BYLINE_PASSKEY_ORIGINS?.split(',').map((origin) => origin.trim()) ?? [],
90
+ allowInsecureLocalhost: process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST === 'true',
91
+ } : undefined
92
+ const resolveClientIp = createClientIpResolver({
93
+ // Opt in only when the proxy overwrites this header and direct access is blocked.
94
+ trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
95
+ resolvePeerIp: () => getRequestIP() ??
96
+ (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
97
+ })
98
+ const passkeyRequests = passkeys ? {
99
+ limiter: createPasskeyRequestLimiter(adminStore.signInRateLimits, signingSecret),
100
+ resolveClientIp,
101
+ } : undefined
102
+
82
103
  const sessionProvider = new JwtSessionProvider({
104
+ passkeys,
83
105
  store: adminStore,
84
106
  signingSecret,
85
107
  })
@@ -98,15 +120,12 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
98
120
  baseUrl: '/uploads',
99
121
  }),
100
122
  sessionProvider,
101
- recurringTasks: [signInLimiter.cleanupTask],
123
+ passkeys,
124
+ passkeyRequests,
125
+ recurringTasks: [...createAuthMaintenanceTasks(adminStore), signInLimiter.cleanupTask],
102
126
  passwordSignIn: {
103
127
  limiter: signInLimiter,
104
- resolveClientIp: createClientIpResolver({
105
- // Opt in only when the proxy overwrites this header and direct access is blocked.
106
- trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
107
- resolvePeerIp: () => getRequestIP() ??
108
- (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
109
- }),
128
+ resolveClientIp,
110
129
  },
111
130
  fields: {
112
131
  richText: {
@@ -18,7 +18,7 @@
18
18
  */
19
19
 
20
20
  import { type AdminStore, registerAdminAbilities } from '@byline/admin'
21
- import { createPasswordSignInLimiter, JwtSessionProvider } from '@byline/admin/auth'
21
+ import { createAuthMaintenanceTasks, createPasswordSignInLimiter, createPasskeyRequestLimiter, JwtSessionProvider } from '@byline/admin/auth'
22
22
  import { getRequestIP } from '@tanstack/react-start/server'
23
23
  import { createClientIpResolver } from '@byline/host-tanstack-start/integrations/client-ip'
24
24
  import { type BylineCore, initBylineCore } from '@byline/core'
@@ -86,7 +86,29 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
86
86
 
87
87
  const signInLimiter = createPasswordSignInLimiter(adminStore.signInRateLimits, signingSecret)
88
88
 
89
+ // Passkeys remain disabled until explicit site trust is configured. Never infer
90
+ // relying-party identity or origins from request headers.
91
+ const passkeys = [process.env.BYLINE_PASSKEY_RP_ID, process.env.BYLINE_PASSKEY_RP_NAME,
92
+ process.env.BYLINE_PASSKEY_ORIGINS, process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST]
93
+ .some((value) => value !== undefined) ? {
94
+ rpId: process.env.BYLINE_PASSKEY_RP_ID ?? '',
95
+ rpName: process.env.BYLINE_PASSKEY_RP_NAME ?? '',
96
+ origins: process.env.BYLINE_PASSKEY_ORIGINS?.split(',').map((origin) => origin.trim()) ?? [],
97
+ allowInsecureLocalhost: process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST === 'true',
98
+ } : undefined
99
+ const resolveClientIp = createClientIpResolver({
100
+ // Opt in only when the proxy overwrites this header and direct access is blocked.
101
+ trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
102
+ resolvePeerIp: () => getRequestIP() ??
103
+ (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
104
+ })
105
+ const passkeyRequests = passkeys ? {
106
+ limiter: createPasskeyRequestLimiter(adminStore.signInRateLimits, signingSecret),
107
+ resolveClientIp,
108
+ } : undefined
109
+
89
110
  const sessionProvider = new JwtSessionProvider({
111
+ passkeys,
90
112
  store: adminStore,
91
113
  signingSecret,
92
114
  })
@@ -140,15 +162,12 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
140
162
  // cacheControl: 'public, max-age=31536000, immutable',
141
163
  // }),
142
164
  sessionProvider,
143
- recurringTasks: [signInLimiter.cleanupTask],
165
+ passkeys,
166
+ passkeyRequests,
167
+ recurringTasks: [...createAuthMaintenanceTasks(adminStore), signInLimiter.cleanupTask],
144
168
  passwordSignIn: {
145
169
  limiter: signInLimiter,
146
- resolveClientIp: createClientIpResolver({
147
- // Opt in only when the proxy overwrites this header and direct access is blocked.
148
- trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
149
- resolvePeerIp: () => getRequestIP() ??
150
- (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
151
- }),
170
+ resolveClientIp,
152
171
  },
153
172
  fields: {
154
173
  richText: {
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  import { type AdminStore, registerAdminAbilities } from '@byline/admin'
18
- import { createPasswordSignInLimiter, JwtSessionProvider } from '@byline/admin/auth'
18
+ import { createAuthMaintenanceTasks, createPasswordSignInLimiter, createPasskeyRequestLimiter, JwtSessionProvider } from '@byline/admin/auth'
19
19
  import { getRequestIP } from '@tanstack/react-start/server'
20
20
  import { createClientIpResolver } from '@byline/host-tanstack-start/integrations/client-ip'
21
21
  import { type BylineCore, initBylineCore } from '@byline/core'
@@ -134,7 +134,29 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
134
134
 
135
135
  const signInLimiter = createPasswordSignInLimiter(adminStore.signInRateLimits, signingSecret)
136
136
 
137
+ // Passkeys remain disabled until explicit site trust is configured. Never infer
138
+ // relying-party identity or origins from request headers.
139
+ const passkeys = [process.env.BYLINE_PASSKEY_RP_ID, process.env.BYLINE_PASSKEY_RP_NAME,
140
+ process.env.BYLINE_PASSKEY_ORIGINS, process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST]
141
+ .some((value) => value !== undefined) ? {
142
+ rpId: process.env.BYLINE_PASSKEY_RP_ID ?? '',
143
+ rpName: process.env.BYLINE_PASSKEY_RP_NAME ?? '',
144
+ origins: process.env.BYLINE_PASSKEY_ORIGINS?.split(',').map((origin) => origin.trim()) ?? [],
145
+ allowInsecureLocalhost: process.env.BYLINE_PASSKEY_ALLOW_HTTP_LOCALHOST === 'true',
146
+ } : undefined
147
+ const resolveClientIp = createClientIpResolver({
148
+ // Opt in only when the proxy overwrites this header and direct access is blocked.
149
+ trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
150
+ resolvePeerIp: () => getRequestIP() ??
151
+ (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
152
+ })
153
+ const passkeyRequests = passkeys ? {
154
+ limiter: createPasskeyRequestLimiter(adminStore.signInRateLimits, signingSecret),
155
+ resolveClientIp,
156
+ } : undefined
157
+
137
158
  const sessionProvider = new JwtSessionProvider({
159
+ passkeys,
138
160
  store: adminStore,
139
161
  signingSecret,
140
162
  })
@@ -194,15 +216,12 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
194
216
  // cacheControl: 'public, max-age=31536000, immutable',
195
217
  // }),
196
218
  sessionProvider,
197
- recurringTasks: [signInLimiter.cleanupTask],
219
+ passkeys,
220
+ passkeyRequests,
221
+ recurringTasks: [...createAuthMaintenanceTasks(adminStore), signInLimiter.cleanupTask],
198
222
  passwordSignIn: {
199
223
  limiter: signInLimiter,
200
- resolveClientIp: createClientIpResolver({
201
- // Opt in only when the proxy overwrites this header and direct access is blocked.
202
- trustedProxyHeader: process.env.BYLINE_TRUSTED_CLIENT_IP_HEADER || undefined,
203
- resolvePeerIp: () => getRequestIP() ??
204
- (process.env.NODE_ENV === 'development' ? '127.0.0.1' : null),
205
- }),
224
+ resolveClientIp,
206
225
  },
207
226
  fields: {
208
227
  // Server-side richtext adapter — refreshes embedded relation
@@ -7,6 +7,40 @@ CREATE TABLE `byline_admin_login_sessions` (
7
7
  CONSTRAINT `byline_admin_login_sessions_id` PRIMARY KEY(`id`)
8
8
  );
9
9
  --> statement-breakpoint
10
+ CREATE TABLE `byline_admin_passkey_attempts` (
11
+ `token_hash` varbinary(64) NOT NULL,
12
+ `purpose` varchar(24) NOT NULL,
13
+ `challenge` varchar(43),
14
+ `actor_user_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
15
+ `actor_login_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
16
+ `actor_generation` int,
17
+ `action` varchar(8),
18
+ `target_user_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
19
+ `credential_record_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
20
+ `proof_credential_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
21
+ `created_at` datetime(6) NOT NULL,
22
+ `expires_at` datetime(6) NOT NULL,
23
+ `consumed_at` datetime(6),
24
+ CONSTRAINT `byline_admin_passkey_attempts_token_hash` PRIMARY KEY(`token_hash`)
25
+ );
26
+ --> statement-breakpoint
27
+ CREATE TABLE `byline_admin_passkey_credentials` (
28
+ `id` char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
29
+ `admin_user_id` char(36) CHARACTER SET ascii COLLATE ascii_bin,
30
+ `credential_id` varbinary(1366) NOT NULL,
31
+ `public_key` text NOT NULL,
32
+ `counter` bigint NOT NULL,
33
+ `transports` json NOT NULL,
34
+ `backup_eligible` boolean NOT NULL,
35
+ `backed_up` boolean NOT NULL,
36
+ `name` varchar(80) NOT NULL,
37
+ `created_at` datetime(6) NOT NULL,
38
+ `last_used_at` datetime(6),
39
+ `revoked_at` datetime(6),
40
+ CONSTRAINT `byline_admin_passkey_credentials_id` PRIMARY KEY(`id`),
41
+ CONSTRAINT `byline_admin_passkey_credentials_credential_id_unique` UNIQUE(`credential_id`)
42
+ );
43
+ --> statement-breakpoint
10
44
  CREATE TABLE `byline_admin_permissions` (
11
45
  `id` char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
12
46
  `vid` int NOT NULL DEFAULT 1,
@@ -75,6 +109,7 @@ CREATE TABLE `byline_admin_user_preferences` (
75
109
  --> statement-breakpoint
76
110
  CREATE TABLE `byline_admin_users` (
77
111
  `id` char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
112
+ `webauthn_user_handle` varbinary(43),
78
113
  `session_version` int NOT NULL DEFAULT 0,
79
114
  `vid` int NOT NULL DEFAULT 1,
80
115
  `given_name` varchar(100),
@@ -93,6 +128,7 @@ CREATE TABLE `byline_admin_users` (
93
128
  `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
94
129
  `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
95
130
  CONSTRAINT `byline_admin_users_id` PRIMARY KEY(`id`),
131
+ CONSTRAINT `byline_admin_users_webauthn_user_handle_unique` UNIQUE(`webauthn_user_handle`),
96
132
  CONSTRAINT `byline_admin_users_username_unique` UNIQUE(`username`),
97
133
  CONSTRAINT `byline_admin_users_email_unique` UNIQUE(`email`)
98
134
  );
@@ -397,6 +433,7 @@ CREATE TABLE `byline_store_text` (
397
433
  );
398
434
  --> statement-breakpoint
399
435
  ALTER TABLE `byline_admin_login_sessions` ADD CONSTRAINT `fk_admin_login_sessions_user` FOREIGN KEY (`admin_user_id`) REFERENCES `byline_admin_users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
436
+ ALTER TABLE `byline_admin_passkey_credentials` ADD CONSTRAINT `fk_admin_passkeys_user` FOREIGN KEY (`admin_user_id`) REFERENCES `byline_admin_users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
400
437
  ALTER TABLE `byline_admin_permissions` ADD CONSTRAINT `fk_admin_permissions_admin_role_id` FOREIGN KEY (`admin_role_id`) REFERENCES `byline_admin_roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
401
438
  ALTER TABLE `byline_admin_refresh_tokens` ADD CONSTRAINT `fk_admin_refresh_tokens_sid` FOREIGN KEY (`sid`) REFERENCES `byline_admin_login_sessions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
402
439
  ALTER TABLE `byline_admin_refresh_tokens` ADD CONSTRAINT `fk_admin_refresh_tokens_admin_user_id` FOREIGN KEY (`admin_user_id`) REFERENCES `byline_admin_users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
@@ -436,8 +473,15 @@ ALTER TABLE `byline_singleton_documents` ADD CONSTRAINT `fk_singleton_documents_
436
473
  ALTER TABLE `byline_store_text` ADD CONSTRAINT `fk_store_text_document_version_id` FOREIGN KEY (`document_version_id`) REFERENCES `byline_document_versions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
437
474
  ALTER TABLE `byline_store_text` ADD CONSTRAINT `fk_store_text_collection_id` FOREIGN KEY (`collection_id`) REFERENCES `byline_collections`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
438
475
  CREATE INDEX `idx_admin_login_sessions_user` ON `byline_admin_login_sessions` (`admin_user_id`);--> statement-breakpoint
476
+ CREATE INDEX `idx_admin_login_sessions_expiry` ON `byline_admin_login_sessions` (`expires_at`);--> statement-breakpoint
477
+ CREATE INDEX `idx_admin_login_sessions_revoked` ON `byline_admin_login_sessions` (`revoked_at`);--> statement-breakpoint
478
+ CREATE INDEX `idx_admin_passkey_attempts_expiry` ON `byline_admin_passkey_attempts` (`expires_at`);--> statement-breakpoint
479
+ CREATE INDEX `idx_admin_passkey_attempts_consumed` ON `byline_admin_passkey_attempts` (`consumed_at`);--> statement-breakpoint
480
+ CREATE INDEX `idx_admin_passkey_attempts_login` ON `byline_admin_passkey_attempts` (`actor_login_id`);--> statement-breakpoint
481
+ CREATE INDEX `idx_admin_passkeys_user` ON `byline_admin_passkey_credentials` (`admin_user_id`);--> statement-breakpoint
439
482
  CREATE INDEX `idx_byline_admin_permissions_role` ON `byline_admin_permissions` (`admin_role_id`);--> statement-breakpoint
440
483
  CREATE INDEX `idx_admin_refresh_tokens_sid` ON `byline_admin_refresh_tokens` (`sid`);--> statement-breakpoint
484
+ CREATE INDEX `idx_admin_refresh_tokens_legacy_expiry` ON `byline_admin_refresh_tokens` (`sid`,`expires_at`);--> statement-breakpoint
441
485
  CREATE INDEX `idx_byline_admin_refresh_tokens_user` ON `byline_admin_refresh_tokens` (`admin_user_id`);--> statement-breakpoint
442
486
  CREATE INDEX `idx_byline_admin_refresh_tokens_token_hash` ON `byline_admin_refresh_tokens` (`token_hash`);--> statement-breakpoint
443
487
  CREATE INDEX `idx_byline_admin_role_admin_user_user` ON `byline_admin_role_admin_user` (`admin_user_id`);--> statement-breakpoint
@@ -5,8 +5,8 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "5",
8
- "when": 1788879988783,
9
- "tag": "0000_kind_exodus",
8
+ "when": 1792124008486,
9
+ "tag": "0000_volatile_agent_brand",
10
10
  "breakpoints": true
11
11
  }
12
12
  ]
@@ -6,6 +6,38 @@ CREATE TABLE "byline_admin_login_sessions" (
6
6
  "revoked_at" timestamp (6) with time zone
7
7
  );
8
8
  --> statement-breakpoint
9
+ CREATE TABLE "byline_admin_passkey_attempts" (
10
+ "token_hash" varchar(64) COLLATE "C" PRIMARY KEY NOT NULL,
11
+ "purpose" varchar(24) NOT NULL,
12
+ "challenge" varchar(43),
13
+ "actor_user_id" uuid,
14
+ "actor_login_id" uuid,
15
+ "actor_generation" integer,
16
+ "action" varchar(8),
17
+ "target_user_id" uuid,
18
+ "credential_record_id" uuid,
19
+ "proof_credential_id" uuid,
20
+ "created_at" timestamp (6) with time zone NOT NULL,
21
+ "expires_at" timestamp (6) with time zone NOT NULL,
22
+ "consumed_at" timestamp (6) with time zone
23
+ );
24
+ --> statement-breakpoint
25
+ CREATE TABLE "byline_admin_passkey_credentials" (
26
+ "id" uuid PRIMARY KEY NOT NULL,
27
+ "admin_user_id" uuid,
28
+ "credential_id" varchar(1366) COLLATE "C" NOT NULL,
29
+ "public_key" text NOT NULL,
30
+ "counter" bigint NOT NULL,
31
+ "transports" jsonb NOT NULL,
32
+ "backup_eligible" boolean NOT NULL,
33
+ "backed_up" boolean NOT NULL,
34
+ "name" varchar(80) NOT NULL,
35
+ "created_at" timestamp (6) with time zone NOT NULL,
36
+ "last_used_at" timestamp (6) with time zone,
37
+ "revoked_at" timestamp (6) with time zone,
38
+ CONSTRAINT "byline_admin_passkey_credentials_credential_id_unique" UNIQUE("credential_id")
39
+ );
40
+ --> statement-breakpoint
9
41
  CREATE TABLE "byline_admin_permissions" (
10
42
  "id" uuid PRIMARY KEY NOT NULL,
11
43
  "vid" integer DEFAULT 1 NOT NULL,
@@ -70,6 +102,7 @@ CREATE TABLE "byline_admin_user_preferences" (
70
102
  --> statement-breakpoint
71
103
  CREATE TABLE "byline_admin_users" (
72
104
  "id" uuid PRIMARY KEY NOT NULL,
105
+ "webauthn_user_handle" varchar(43) COLLATE "C",
73
106
  "session_version" integer DEFAULT 0 NOT NULL,
74
107
  "vid" integer DEFAULT 1 NOT NULL,
75
108
  "given_name" varchar(100),
@@ -87,6 +120,7 @@ CREATE TABLE "byline_admin_users" (
87
120
  "preferred_locale" varchar(16),
88
121
  "created_at" timestamp (6) with time zone DEFAULT now() NOT NULL,
89
122
  "updated_at" timestamp (6) with time zone DEFAULT now() NOT NULL,
123
+ CONSTRAINT "byline_admin_users_webauthn_user_handle_unique" UNIQUE("webauthn_user_handle"),
90
124
  CONSTRAINT "byline_admin_users_username_unique" UNIQUE("username"),
91
125
  CONSTRAINT "byline_admin_users_email_unique" UNIQUE("email")
92
126
  );
@@ -374,6 +408,7 @@ CREATE TABLE "byline_store_text" (
374
408
  );
375
409
  --> statement-breakpoint
376
410
  ALTER TABLE "byline_admin_login_sessions" ADD CONSTRAINT "byline_admin_login_sessions_admin_user_id_byline_admin_users_id_fk" FOREIGN KEY ("admin_user_id") REFERENCES "public"."byline_admin_users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
411
+ ALTER TABLE "byline_admin_passkey_credentials" ADD CONSTRAINT "byline_admin_passkey_credentials_admin_user_id_byline_admin_users_id_fk" FOREIGN KEY ("admin_user_id") REFERENCES "public"."byline_admin_users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
377
412
  ALTER TABLE "byline_admin_permissions" ADD CONSTRAINT "byline_admin_permissions_admin_role_id_byline_admin_roles_id_fk" FOREIGN KEY ("admin_role_id") REFERENCES "public"."byline_admin_roles"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
378
413
  ALTER TABLE "byline_admin_refresh_tokens" ADD CONSTRAINT "byline_admin_refresh_tokens_admin_user_id_byline_admin_users_id_fk" FOREIGN KEY ("admin_user_id") REFERENCES "public"."byline_admin_users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
379
414
  ALTER TABLE "byline_admin_refresh_tokens" ADD CONSTRAINT "byline_admin_refresh_tokens_sid_byline_admin_login_sessions_id_fk" FOREIGN KEY ("sid") REFERENCES "public"."byline_admin_login_sessions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
@@ -413,8 +448,15 @@ ALTER TABLE "byline_singleton_documents" ADD CONSTRAINT "fk_singleton_documents_
413
448
  ALTER TABLE "byline_store_text" ADD CONSTRAINT "byline_store_text_document_version_id_byline_document_versions_id_fk" FOREIGN KEY ("document_version_id") REFERENCES "public"."byline_document_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
414
449
  ALTER TABLE "byline_store_text" ADD CONSTRAINT "byline_store_text_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
415
450
  CREATE INDEX "idx_admin_login_sessions_user" ON "byline_admin_login_sessions" USING btree ("admin_user_id");--> statement-breakpoint
451
+ CREATE INDEX "idx_admin_login_sessions_expiry" ON "byline_admin_login_sessions" USING btree ("expires_at");--> statement-breakpoint
452
+ CREATE INDEX "idx_admin_login_sessions_revoked" ON "byline_admin_login_sessions" USING btree ("revoked_at");--> statement-breakpoint
453
+ CREATE INDEX "idx_admin_passkey_attempts_expiry" ON "byline_admin_passkey_attempts" USING btree ("expires_at");--> statement-breakpoint
454
+ CREATE INDEX "idx_admin_passkey_attempts_consumed" ON "byline_admin_passkey_attempts" USING btree ("consumed_at");--> statement-breakpoint
455
+ CREATE INDEX "idx_admin_passkey_attempts_login" ON "byline_admin_passkey_attempts" USING btree ("actor_login_id");--> statement-breakpoint
456
+ CREATE INDEX "idx_admin_passkeys_user" ON "byline_admin_passkey_credentials" USING btree ("admin_user_id");--> statement-breakpoint
416
457
  CREATE INDEX "idx_byline_admin_permissions_role" ON "byline_admin_permissions" USING btree ("admin_role_id");--> statement-breakpoint
417
458
  CREATE INDEX "idx_admin_refresh_tokens_sid" ON "byline_admin_refresh_tokens" USING btree ("sid");--> statement-breakpoint
459
+ CREATE INDEX "idx_admin_refresh_tokens_legacy_expiry" ON "byline_admin_refresh_tokens" USING btree ("sid","expires_at");--> statement-breakpoint
418
460
  CREATE INDEX "idx_byline_admin_refresh_tokens_user" ON "byline_admin_refresh_tokens" USING btree ("admin_user_id");--> statement-breakpoint
419
461
  CREATE INDEX "idx_byline_admin_refresh_tokens_token_hash" ON "byline_admin_refresh_tokens" USING btree ("token_hash");--> statement-breakpoint
420
462
  CREATE INDEX "idx_byline_admin_role_admin_user_user" ON "byline_admin_role_admin_user" USING btree ("admin_user_id");--> statement-breakpoint
@@ -5,8 +5,8 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "7",
8
- "when": 1788880329240,
9
- "tag": "0000_lively_talisman",
8
+ "when": 1792123994697,
9
+ "tag": "0000_superb_ben_parker",
10
10
  "breakpoints": true
11
11
  }
12
12
  ]
package/package.json CHANGED
@@ -2,9 +2,9 @@
2
2
  "name": "@byline/cli",
3
3
  "private": false,
4
4
  "license": "MPL-2.0",
5
- "version": "6.7.1",
5
+ "version": "6.8.0",
6
6
  "engines": {
7
- "node": ">=20.9.0"
7
+ "node": ">=22.22.2"
8
8
  },
9
9
  "description": "Guided installer for Byline CMS into an existing TanStack Start application",
10
10
  "keywords": [
@@ -36,32 +36,32 @@
36
36
  "@clack/prompts": "^1.8.1",
37
37
  "commander": "^15.0.0",
38
38
  "diff": "^9.0.0",
39
- "drizzle-orm": "^0.45.2",
40
- "execa": "^10.0.1",
39
+ "drizzle-orm": "^0.45.4",
40
+ "execa": "^10.1.1",
41
41
  "jsonc-parser": "^3.3.1",
42
42
  "minimatch": "^10.2.6",
43
- "mysql2": "^3.24.4",
44
- "pg": "^8.23.0",
43
+ "mysql2": "^3.24.6",
44
+ "pg": "^8.23.1",
45
45
  "picocolors": "^1.1.1",
46
46
  "semver": "^7.8.5",
47
47
  "ts-morph": "^28.0.0",
48
48
  "yaml": "^2.9.1"
49
49
  },
50
50
  "devDependencies": {
51
- "@biomejs/biome": "2.5.14",
51
+ "@biomejs/biome": "2.5.15",
52
+ "@byline/core": "6.8.0",
52
53
  "@types/mdast": "^4.0.4",
53
- "@types/node": "^26.6.2",
54
+ "@types/node": "^26.6.5",
54
55
  "@types/pg": "^8.23.1",
55
56
  "@types/semver": "^7.8.0",
56
- "dotenv": "^18.0.1",
57
+ "dotenv": "^18.0.8",
57
58
  "mdast-util-to-string": "^4.0.0",
58
59
  "remark-gfm": "^4.0.1",
59
60
  "remark-parse": "^11.0.0",
60
- "tsc-alias": "^1.9.5",
61
+ "tsc-alias": "^1.9.7",
61
62
  "typescript": "^7.0.2",
62
63
  "unified": "^11.0.5",
63
- "vitest": "^5.0.1",
64
- "@byline/core": "6.7.1"
64
+ "vitest": "^5.0.4"
65
65
  },
66
66
  "publishConfig": {
67
67
  "access": "public",
@@ -1,11 +0,0 @@
1
- export interface PgConn {
2
- host: string;
3
- port: number;
4
- user: string;
5
- password: string;
6
- database: string;
7
- }
8
- export declare function buildPgUrl(c: PgConn): string;
9
- export declare function parsePgUrl(raw: string): PgConn;
10
- export declare function withDatabase(c: PgConn, database: string): PgConn;
11
- //# sourceMappingURL=pg-url.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pg-url.d.ts","sourceRoot":"","sources":["../../src/lib/pg-url.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAY9C;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE"}
@@ -1,22 +0,0 @@
1
- export function buildPgUrl(c) {
2
- const u = encodeURIComponent(c.user);
3
- const p = encodeURIComponent(c.password);
4
- return `postgresql://${u}:${p}@${c.host}:${c.port}/${encodeURIComponent(c.database)}`;
5
- }
6
- export function parsePgUrl(raw) {
7
- const url = new URL(raw);
8
- if (url.protocol !== 'postgresql:' && url.protocol !== 'postgres:') {
9
- throw new Error(`expected postgresql:// URL, got ${url.protocol}`);
10
- }
11
- return {
12
- host: url.hostname,
13
- port: url.port ? Number(url.port) : 5432,
14
- user: decodeURIComponent(url.username),
15
- password: decodeURIComponent(url.password),
16
- database: url.pathname.replace(/^\//, '') || 'postgres',
17
- };
18
- }
19
- export function withDatabase(c, database) {
20
- return { ...c, database };
21
- }
22
- //# sourceMappingURL=pg-url.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pg-url.js","sourceRoot":"","sources":["../../src/lib/pg-url.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACxC,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAA;AACvF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IACpE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QACxC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACtC,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1C,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,UAAU;KACxD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,QAAgB;IACtD,OAAO,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAA;AAC3B,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Phase, PhaseId } from '../types.js';
2
- export declare function stubPhase(id: PhaseId, title: string): Phase;
3
- //# sourceMappingURL=stub.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../src/phases/stub.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAEjD,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAoB3D"}
@@ -1,25 +0,0 @@
1
- export function stubPhase(id, title) {
2
- return {
3
- id,
4
- title,
5
- defaultMode: 'confirm',
6
- async detect(ctx) {
7
- return ctx.state.isComplete(id) ? 'done' : 'pending';
8
- },
9
- async plan() {
10
- return {
11
- writes: [],
12
- commands: [],
13
- notes: [`${id}: not yet implemented in @byline/cli ${currentVersion()}`],
14
- };
15
- },
16
- async apply(_plan, ctx) {
17
- ctx.logger.warn(`${id} — phase is stubbed; please follow the manual instructions in docs`);
18
- return { state: 'pending' };
19
- },
20
- };
21
- }
22
- function currentVersion() {
23
- return '0.1.0';
24
- }
25
- //# sourceMappingURL=stub.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stub.js","sourceRoot":"","sources":["../../src/phases/stub.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,SAAS,CAAC,EAAW,EAAE,KAAa;IAClD,OAAO;QACL,EAAE;QACF,KAAK;QACL,WAAW,EAAE,SAAS;QACtB,KAAK,CAAC,MAAM,CAAC,GAAY;YACvB,OAAO,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;QACtD,CAAC;QACD,KAAK,CAAC,IAAI;YACR,OAAO;gBACL,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,CAAC,GAAG,EAAE,wCAAwC,cAAc,EAAE,EAAE,CAAC;aACzE,CAAA;QACH,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG;YACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,oEAAoE,CAAC,CAAA;YAC1F,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QAC7B,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -1,2 +0,0 @@
1
- export declare function renderSnippet(title: string, body: string, lang?: string): string;
2
- //# sourceMappingURL=snippet.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"snippet.d.ts","sourceRoot":"","sources":["../../src/ui/snippet.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,MAAM,CAI5E"}
@@ -1,7 +0,0 @@
1
- import pc from 'picocolors';
2
- export function renderSnippet(title, body, lang = '') {
3
- const header = pc.dim(`--- ${title}${lang ? ` (${lang})` : ''} ---`);
4
- const footer = pc.dim('---');
5
- return `${header}\n${body}\n${footer}`;
6
- }
7
- //# sourceMappingURL=snippet.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"snippet.js","sourceRoot":"","sources":["../../src/ui/snippet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,IAAY,EAAE,IAAI,GAAG,EAAE;IAClE,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IACpE,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC5B,OAAO,GAAG,MAAM,KAAK,IAAI,KAAK,MAAM,EAAE,CAAA;AACxC,CAAC"}