@getstrata/starter 1.1.5 → 1.1.6

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.
package/dist/cli.js CHANGED
@@ -120,7 +120,7 @@ function extraApplies(extra, auth) {
120
120
  if (extra === "metrics" || extra === "billing" || extra === "webhooks") {
121
121
  return true;
122
122
  }
123
- if (extra === "mfa" || extra === "oauthGithub") {
123
+ if (extra === "mfa" || extra === "oauthGithub" || extra === "oidc") {
124
124
  return htmlAuthKit(auth);
125
125
  }
126
126
  return authNeedsUsers(auth);
@@ -196,6 +196,7 @@ var noneExtras = {
196
196
  scim: false,
197
197
  metrics: false,
198
198
  oauthGithub: false,
199
+ oidc: false,
199
200
  billing: false,
200
201
  webhooks: false
201
202
  };
@@ -205,6 +206,7 @@ var enterpriseExtras = {
205
206
  scim: true,
206
207
  metrics: true,
207
208
  oauthGithub: false,
209
+ oidc: false,
208
210
  billing: false,
209
211
  webhooks: false
210
212
  };
@@ -274,9 +276,10 @@ Options:
274
276
  --scim / --no-scim
275
277
  --metrics / --no-metrics
276
278
  --oauth-github / --no-oauth-github
279
+ --oidc / --no-oidc
277
280
  --billing / --no-billing
278
281
  --webhooks / --no-webhooks
279
- --extras Interactive extras list (MFA, email verification, SCIM, metrics, GitHub OAuth, billing, webhooks)
282
+ --extras Interactive extras list (MFA, email verification, SCIM, metrics, GitHub OAuth, OIDC, billing, webhooks)
280
283
  --docker Write Docker Compose for every selected tool that needs a service
281
284
  --no-docker Skip docker-compose.yml; use installs already on this machine
282
285
  --docker-services Subset: postgres, mysql, redis, mailpit, adminer (comma-separated)
@@ -382,6 +385,8 @@ function parseCreateStrataArgs(argv) {
382
385
  ["--no-metrics", "metrics", false],
383
386
  ["--oauth-github", "oauthGithub", true],
384
387
  ["--no-oauth-github", "oauthGithub", false],
388
+ ["--oidc", "oidc", true],
389
+ ["--no-oidc", "oidc", false],
385
390
  ["--billing", "billing", true],
386
391
  ["--no-billing", "billing", false],
387
392
  ["--webhooks", "webhooks", true],
@@ -509,6 +514,9 @@ function extraFlagName(extra) {
509
514
  if (extra === "oauthGithub") {
510
515
  return "oauth-github";
511
516
  }
517
+ if (extra === "oidc") {
518
+ return "oidc";
519
+ }
512
520
  return extra;
513
521
  }
514
522
  function dropInapplicableExtras(layers, flags) {
@@ -912,6 +920,7 @@ var EXTRA_CHOICES = [
912
920
  { value: "scim", label: "scim: /Users adapter" },
913
921
  { value: "metrics", label: "metrics: Prometheus token" },
914
922
  { value: "oauthGithub", label: "oauth-github: GitHub cookie login at /auth/github" },
923
+ { value: "oidc", label: "oidc: OIDC cookie login at /auth/oidc (PKCE cookie)" },
915
924
  { value: "billing", label: "billing: Stripe webhook stub + GET /api/v1/billing/subscription" },
916
925
  { value: "webhooks", label: "webhooks: outbound notes.created job (webhook.dispatch)" }
917
926
  ];
@@ -1200,6 +1209,7 @@ function renderAuthModule(layers) {
1200
1209
  }
1201
1210
  const cookie = htmlAuthKit(layers.auth);
1202
1211
  const github = Boolean(layers.extras.oauthGithub && cookie);
1212
+ const oidc = Boolean(layers.extras.oidc && cookie);
1203
1213
  const mfa = Boolean(layers.extras.mfa && cookie);
1204
1214
  const verify = Boolean(layers.extras.emailVerification);
1205
1215
  const jsonApi = authUsesToken(layers.auth) || authUsesJwt(layers.auth);
@@ -1221,6 +1231,11 @@ function renderAuthModule(layers) {
1221
1231
  imports.push(`import { createSamlServiceProvider } from "@getstrata/core/auth/saml/samlServiceProvider";`);
1222
1232
  if (github) {
1223
1233
  imports.push(`import { GitHubOAuthProvider } from "@getstrata/core/auth/oauth/providers";`);
1234
+ }
1235
+ if (oidc) {
1236
+ imports.push(`import { OidcProvider } from "@getstrata/core/auth/oauth/oidcProvider";`);
1237
+ }
1238
+ if (github || oidc) {
1224
1239
  imports.push(`import { appUrl } from "@getstrata/core/runtime/appKeyPrefix";`);
1225
1240
  }
1226
1241
  }
@@ -1251,7 +1266,7 @@ function renderAuthModule(layers) {
1251
1266
  if (mfa) {
1252
1267
  imports.push(`import { sanitizeInternalPath } from "@getstrata/core/http/safeInternalPath";`);
1253
1268
  }
1254
- imports.push(`import { createOAuthState, verifyOAuthState } from "@getstrata/core/security/oauthState";`);
1269
+ imports.push(oidc ? `import { clearOidcPkceCookie, createOAuthState, readOidcPkceCookie, sealOidcPkceCookie, verifyOAuthState } from "@getstrata/core/security/oauthState";` : `import { createOAuthState, verifyOAuthState } from "@getstrata/core/security/oauthState";`);
1255
1270
  }
1256
1271
  if (jsonApi || cookie) {
1257
1272
  imports.push(`import { jsonResponse, withErrorHandling } from "@getstrata/core/http/response";`);
@@ -1692,9 +1707,67 @@ async function completeBrowserSsoLogin(
1692
1707
  return completeBrowserSsoLogin(dependencies, profile, "GitHub");
1693
1708
  })),
1694
1709
  },` : "";
1710
+ const oidcRoutes = oidc ? `
1711
+ "/auth/oidc": {
1712
+ GET: kernel.wrap("api", withErrorHandling(async () => {
1713
+ if (process.env.FEATURE_OAUTH !== "true") {
1714
+ return new Response("Not found", { status: 404 });
1715
+ }
1716
+ const issuer = process.env.OIDC_ISSUER?.trim();
1717
+ const clientId = process.env.OIDC_CLIENT_ID?.trim();
1718
+ const clientSecret = process.env.OIDC_CLIENT_SECRET?.trim();
1719
+ if (!issuer || !clientId || !clientSecret) {
1720
+ return new Response("Not found", { status: 404 });
1721
+ }
1722
+ const redirectUri = process.env.OIDC_REDIRECT_URI?.trim() || \`\${appUrl()}/auth/oidc/callback\`;
1723
+ const issued = createOAuthState();
1724
+ const provider = new OidcProvider({ name: "oidc", issuer, clientId, clientSecret, redirectUri });
1725
+ const { url, handshake } = await provider.createAuthorization(issued.state);
1726
+ const redirect = new Response(null, { status: 302, headers: { location: url } });
1727
+ redirect.headers.append(
1728
+ "set-cookie",
1729
+ sealOidcPkceCookie({ state: issued.state, nonce: handshake.nonce, codeVerifier: handshake.codeVerifier }),
1730
+ );
1731
+ return redirect;
1732
+ })),
1733
+ },
1734
+ "/auth/oidc/callback": {
1735
+ GET: kernel.wrap("api", withErrorHandling(async (request) => {
1736
+ if (process.env.FEATURE_OAUTH !== "true") {
1737
+ return new Response("Not found", { status: 404 });
1738
+ }
1739
+ const issuer = process.env.OIDC_ISSUER?.trim();
1740
+ const clientId = process.env.OIDC_CLIENT_ID?.trim();
1741
+ const clientSecret = process.env.OIDC_CLIENT_SECRET?.trim();
1742
+ if (!issuer || !clientId || !clientSecret) {
1743
+ return new Response("Not found", { status: 404 });
1744
+ }
1745
+ const url = new URL(request.url);
1746
+ const code = url.searchParams.get("code");
1747
+ const state = url.searchParams.get("state");
1748
+ const pkce = readOidcPkceCookie(request, state);
1749
+ if (!code || !verifyOAuthState(request, state) || !pkce) {
1750
+ const denied = jsonResponse({ error: "Invalid OIDC state." }, { status: 403 });
1751
+ denied.headers.append("set-cookie", clearOidcPkceCookie());
1752
+ return denied;
1753
+ }
1754
+ const redirectUri = process.env.OIDC_REDIRECT_URI?.trim() || \`\${appUrl()}/auth/oidc/callback\`;
1755
+ const profile = await new OidcProvider({ name: "oidc", issuer, clientId, clientSecret, redirectUri })
1756
+ .exchangeCode(code, redirectUri, pkce)
1757
+ .catch(() => null);
1758
+ if (!profile) {
1759
+ const failed = jsonResponse({ error: "Invalid OIDC response." }, { status: 400 });
1760
+ failed.headers.append("set-cookie", clearOidcPkceCookie());
1761
+ return failed;
1762
+ }
1763
+ const login = await completeBrowserSsoLogin(dependencies, profile, "OIDC");
1764
+ login.headers.append("set-cookie", clearOidcPkceCookie());
1765
+ return login;
1766
+ })),
1767
+ },` : "";
1695
1768
  const apiRoutes = jsonApi || cookie ? `
1696
1769
  routes({ kernel, dependencies }) {
1697
- return {${csrfRoute}${samlRoutes}${githubRoutes}${cookieJsonAuth}${tokenLogin}${jsonRegister}${jwtLogin}${apiUser}${jsonPassword}${jsonVerify}
1770
+ return {${csrfRoute}${samlRoutes}${githubRoutes}${oidcRoutes}${cookieJsonAuth}${tokenLogin}${jsonRegister}${jwtLogin}${apiUser}${jsonPassword}${jsonVerify}
1698
1771
  };
1699
1772
  },` : "";
1700
1773
  const mfaLoginBranch = `const mfaResult = completePasswordLogin(user, { mfaCode: mfa_code });
@@ -2311,9 +2384,11 @@ function textField(name, label, type, extra = "") {
2311
2384
  function renderLoginView(layers) {
2312
2385
  const githubLink = layers.extras.oauthGithub && htmlAuthKit(layers.auth) ? `
2313
2386
  <a href="/auth/github">Sign in with GitHub</a>` : "";
2387
+ const oidcLink = layers.extras.oidc && htmlAuthKit(layers.auth) ? `
2388
+ <a href="/auth/oidc">Sign in with OIDC</a>` : "";
2314
2389
  return renderFormView("Sign in", `${textField("email", "Email", "email", 'required autocomplete="username"')}
2315
2390
  ${textField("password", "Password", "password", 'required autocomplete="current-password"')}`, "Sign in", `<a href="/register">Create account</a>
2316
- <a href="/forgot-password">Forgot password</a>${githubLink}`).replace('action="<%= it.action || "" %>"', 'action="/login"');
2391
+ <a href="/forgot-password">Forgot password</a>${githubLink}${oidcLink}`).replace('action="<%= it.action || "" %>"', 'action="/login"');
2317
2392
  }
2318
2393
  function renderRegisterView() {
2319
2394
  return renderFormView("Create account", `${textField("name", "Name", "text", "required")}
@@ -2734,20 +2809,38 @@ function renderEnvExample(projectName, layers) {
2734
2809
  lines.push("# SAML_IDP_ISSUER=");
2735
2810
  lines.push("# SAML_WANT_RESPONSE_SIGNED=");
2736
2811
  lines.push("# SAML_DISABLE_REQUESTED_AUTHN_CONTEXT=");
2737
- const oauthOn = Boolean(layers.extras.oauthGithub);
2738
- lines.push(`FEATURE_OAUTH=${envFlag(oauthOn)}`);
2739
- if (oauthOn) {
2812
+ const githubOn = Boolean(layers.extras.oauthGithub);
2813
+ const oidcOn = Boolean(layers.extras.oidc);
2814
+ lines.push(`FEATURE_OAUTH=${envFlag(githubOn || oidcOn)}`);
2815
+ if (githubOn) {
2740
2816
  lines.push("GITHUB_CLIENT_ID=");
2741
2817
  lines.push("GITHUB_CLIENT_SECRET=");
2742
2818
  lines.push("GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback");
2743
- lines.push("OAUTH_STATE_SECRET=dev-oauth-state-secret-change-me-please-32");
2744
2819
  } else {
2745
2820
  lines.push("# GITHUB_CLIENT_ID=");
2746
2821
  lines.push("# GITHUB_CLIENT_SECRET=");
2747
2822
  lines.push("# GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback");
2823
+ }
2824
+ if (oidcOn) {
2825
+ lines.push("OIDC_ISSUER=http://127.0.0.1:8080");
2826
+ lines.push("OIDC_CLIENT_ID=");
2827
+ lines.push("OIDC_CLIENT_SECRET=");
2828
+ lines.push("OIDC_REDIRECT_URI=http://localhost:3000/auth/oidc/callback");
2829
+ lines.push("# Loopback issuers are allowed when APP_ENV is not production. Other private IdPs:");
2830
+ lines.push("# OIDC_ALLOW_PRIVATE=true");
2831
+ } else {
2832
+ lines.push("# OIDC_ISSUER=");
2833
+ lines.push("# OIDC_CLIENT_ID=");
2834
+ lines.push("# OIDC_CLIENT_SECRET=");
2835
+ lines.push("# OIDC_REDIRECT_URI=http://localhost:3000/auth/oidc/callback");
2836
+ lines.push("# OIDC_ALLOW_PRIVATE=true");
2837
+ }
2838
+ if (githubOn || oidcOn) {
2839
+ lines.push("OAUTH_STATE_SECRET=dev-oauth-state-secret-change-me-please-32");
2840
+ } else {
2748
2841
  lines.push("# OAUTH_STATE_SECRET=");
2749
2842
  }
2750
- lines.push("# OIDC cookie login is not generated. Use GitHub cookie routes (--oauth-github) or app-owned PKCE.");
2843
+ lines.push("# --oidc (cookie HTML) seals PKCE in the oidc_pkce cookie. Do not call OidcProvider.getAuthorizationUrl().");
2751
2844
  const billingOn = Boolean(layers.extras.billing);
2752
2845
  lines.push(`FEATURE_BILLING=${envFlag(billingOn)}`);
2753
2846
  if (billingOn) {
@@ -2966,9 +3059,9 @@ function renderPackageJson(projectName, options = {}) {
2966
3059
  "@getstrata/cli": "workspace:*",
2967
3060
  "@getstrata/core": "workspace:*"
2968
3061
  } : {
2969
- "@getstrata/bootstrap": "^1.1.5",
2970
- "@getstrata/cli": "^1.1.5",
2971
- "@getstrata/core": "^1.1.5"
3062
+ "@getstrata/bootstrap": "^1.1.6",
3063
+ "@getstrata/cli": "^1.1.6",
3064
+ "@getstrata/core": "^1.1.6"
2972
3065
  };
2973
3066
  coreDeps.eta = "^4.6.0";
2974
3067
  if (options.layers?.database === "mysql") {
@@ -3092,6 +3185,9 @@ function renderApiDocs(projectName, layers) {
3092
3185
  if (layers.extras.oauthGithub && authUsesCookie(layers.auth)) {
3093
3186
  rows.push("| `GET` | `/auth/github` | Redirects to GitHub. 404 unless `FEATURE_OAUTH=true`. |", "| `GET` | `/auth/github/callback` | Exchanges the code, JIT user, MFA gate, cookie session. |");
3094
3187
  }
3188
+ if (layers.extras.oidc && authUsesCookie(layers.auth)) {
3189
+ rows.push("| `GET` | `/auth/oidc` | OIDC `createAuthorization()` plus `oidc_pkce` cookie. 404 unless `FEATURE_OAUTH=true`. |", "| `GET` | `/auth/oidc/callback` | Reads PKCE, exchanges the code, JIT user, MFA gate, cookie session. |");
3190
+ }
3095
3191
  const authNote = layers.auth === "headers" ? `Auth is \`headers\`. Send \`x-authenticated-user-id\` (and optional \`x-authenticated-user-role\`) for local work and tests. There are no login endpoints and no \`users\` table. Production must set \`AUTH_DEV_HEADERS=false\`, which turns those headers off and leaves you without a guard, so pick another auth layer before you ship.` : authUsesToken(layers.auth) ? `Sign in with \`GET /api/v1/auth/csrf\` then \`POST /api/v1/auth/login\` (send \`X-CSRF-Token\`), then send \`Authorization: Bearer <token>\` on every request. Tokens are stored hashed in \`api_tokens\` and expire after \`API_TOKEN_DEFAULT_EXPIRY_DAYS\` (30 in \`.env.example\`). The response includes \`expires_at\`.` : `Mint a JWT with \`POST /api/auth/token\`, then send \`Authorization: Bearer <jwt>\`. JWTs expire; re-mint rather than refreshing in place.`;
3096
3192
  return `# ${projectName} API
3097
3193
 
@@ -3146,6 +3242,7 @@ Import from \`@getstrata/core/...\` subpaths rather than the package root, so si
3146
3242
  function renderIntegrationsReadme(layers) {
3147
3243
  const enabled = [
3148
3244
  layers.extras.oauthGithub ? "GitHub OAuth cookie login (`/auth/github`)" : null,
3245
+ layers.extras.oidc ? "OIDC cookie login (`/auth/oidc`, PKCE in `oidc_pkce`)" : null,
3149
3246
  layers.extras.billing ? "Stripe billing stub (`POST /billing/webhooks/stripe`, `GET /api/v1/billing/subscription`)" : null,
3150
3247
  layers.extras.webhooks ? "Outbound webhooks (`notes.created` listener + `webhook.dispatch` job)" : null
3151
3248
  ].filter((row) => row !== null);
@@ -3154,7 +3251,7 @@ function renderIntegrationsReadme(layers) {
3154
3251
  "",
3155
3252
  "OAuth, billing, outbound webhooks, SIEM, and SAML are **off by default**. Commented placeholders live in `.env.example`. Framework map: [INTEGRATIONS.md](https://github.com/EyK-26/strata/blob/main/docs/INTEGRATIONS.md).",
3156
3253
  "",
3157
- "Wizard flags (any stack unless noted): `--oauth-github` (cookie HTML), `--billing`, `--webhooks`. They emit modules, migrations, jobs, or listeners. `createApp` still calls `discoverListeners()` and `discoverJobs()`.",
3254
+ "Wizard flags (any stack unless noted): `--oauth-github` and `--oidc` (cookie HTML), `--billing`, `--webhooks`. They emit modules, migrations, jobs, or listeners. `createApp` still calls `discoverListeners()` and `discoverJobs()`.",
3158
3255
  ""
3159
3256
  ];
3160
3257
  if (enabled.length > 0) {
@@ -3255,7 +3352,7 @@ HTML auth kit (restyle \`views/\` and \`public/assets/site.css\`):
3255
3352
  - Register: \`/register\`
3256
3353
  - Forgot password: \`/forgot-password\`
3257
3354
  - Reset password: signed \`/reset-password\` (mail log when \`MAIL_DRIVER=log\`)
3258
- ${layers.extras.emailVerification ? "- Verify email: `/email/verify`\n" : ""}${layers.extras.mfa ? "- MFA challenge: `/login/mfa` and setup: `/account/mfa`\n" : ""}${layers.extras.oauthGithub ? "- GitHub: `/auth/github` (needs `FEATURE_OAUTH=true`)\n" : ""}
3355
+ ${layers.extras.emailVerification ? "- Verify email: `/email/verify`\n" : ""}${layers.extras.mfa ? "- MFA challenge: `/login/mfa` and setup: `/account/mfa`\n" : ""}${layers.extras.oauthGithub ? "- GitHub: `/auth/github` (needs `FEATURE_OAUTH=true`)\n" : ""}${layers.extras.oidc ? "- OIDC: `/auth/oidc` (needs `FEATURE_OAUTH=true`; PKCE cookie `oidc_pkce`)\n" : ""}
3259
3356
  Cookie name is \`strata_session\`. Forms send CSRF as \`_token\`.
3260
3357
  ` : ""}${authUsesToken(layers.auth) ? `
3261
3358
  Opaque token login: \`POST /api/v1/auth/login\` with \`{ "email", "password" }\`. Register: \`POST /api/v1/auth/register\`. Forgot/reset: \`POST /api/v1/auth/forgot-password\` and signed \`POST /api/v1/auth/reset-password\`. Send \`Authorization: Bearer\` after login.
@@ -3302,7 +3399,7 @@ The image sets \`APP_ENV=production\` and \`AUTH_DEV_HEADERS=false\`; everything
3302
3399
  - Set \`FEATURE_PUBLIC_READS=false\`. Generated \`.env.example\` already ships \`false\` so \`wrapWebPublicRead\` requires a login. Local storefronts may set \`true\` in \`.env\` for an anonymous catalog; \`assertProductionSecrets()\` rejects \`true\` in production. Do not ship a public-reads production boot.
3303
3400
  - Cross-origin browser calls are off in production until you set \`CORS_ALLOWED_ORIGINS\` to explicit origins. A \`*\` entry is rejected. Non-browser clients are unaffected.
3304
3401
  - Behind a reverse proxy or load balancer, set \`TRUST_FORWARDED_FOR=true\` so throttles and session records see the client address instead of the proxy. Only the rightmost public hop of \`X-Forwarded-For\` is trusted.
3305
- ${authUsesCookie(layers.auth) ? "- Set `SESSION_SECRET` to 32+ characters.\n" : ""}${authUsesToken(layers.auth) ? "- Set `TOKEN_HASH_PEPPER`.\n" : ""}${layers.extras.scim ? "- Set `SCIM_BEARER_TOKEN`.\n" : ""}${layers.extras.metrics ? "- Set `METRICS_TOKEN`.\n" : ""}${layers.extras.oauthGithub ? "- Set `OAUTH_STATE_SECRET` and `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`.\n" : ""}${layers.extras.billing ? "- Set `STRIPE_WEBHOOK_SECRET` when `FEATURE_BILLING=true`.\n" : ""}${layers.tenancy === "rls" ? `- \`DATABASE_URL\` must be a \`NOBYPASSRLS\` role, not the \`postgres\` superuser. Generated apps create \`${GENERATED_POSTGRES_APP_ROLE}\` via \`db/ensure-postgres-app-role.sql\` (and Compose init on first empty volume). \`MIGRATION_DATABASE_URL\` may stay the superuser for CREATE ROLE / GRANT / migrate. Production boot rejects username \`postgres\` or \`root\`, then inspects \`pg_roles\` for \`rolsuper\` / \`rolbypassrls\`.
3402
+ ${authUsesCookie(layers.auth) ? "- Set `SESSION_SECRET` to 32+ characters.\n" : ""}${authUsesToken(layers.auth) ? "- Set `TOKEN_HASH_PEPPER`.\n" : ""}${layers.extras.scim ? "- Set `SCIM_BEARER_TOKEN`.\n" : ""}${layers.extras.metrics ? "- Set `METRICS_TOKEN`.\n" : ""}${layers.extras.oauthGithub ? "- Set `OAUTH_STATE_SECRET` and `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`.\n" : ""}${layers.extras.oidc ? "- Set `OAUTH_STATE_SECRET`, `OIDC_ISSUER`, `OIDC_CLIENT_ID`, and `OIDC_CLIENT_SECRET`. Loopback issuers work outside production; set `OIDC_ALLOW_PRIVATE=true` for other private IdPs.\n" : ""}${layers.extras.billing ? "- Set `STRIPE_WEBHOOK_SECRET` when `FEATURE_BILLING=true`.\n" : ""}${layers.tenancy === "rls" ? `- \`DATABASE_URL\` must be a \`NOBYPASSRLS\` role, not the \`postgres\` superuser. Generated apps create \`${GENERATED_POSTGRES_APP_ROLE}\` via \`db/ensure-postgres-app-role.sql\` (and Compose init on first empty volume). \`MIGRATION_DATABASE_URL\` may stay the superuser for CREATE ROLE / GRANT / migrate. Production boot rejects username \`postgres\` or \`root\`, then inspects \`pg_roles\` for \`rolsuper\` / \`rolbypassrls\`.
3306
3403
  ` : ""}
3307
3404
  \`strata start\` does not migrate when \`APP_ENV=production\`. Run \`bun run db:migrate\` as a deploy step. \`GET /health\` is 200 when \`notes\` is readable (including zero rows) and 503 when that read fails. Redis jobs need a worker: \`bun run queue:work\` (requires \`REDIS_URL\`).
3308
3405
  `;
@@ -12,9 +12,9 @@
12
12
  "check": "tsc --noEmit"
13
13
  },
14
14
  "dependencies": {
15
- "@getstrata/bootstrap": "^1.1.5",
16
- "@getstrata/cli": "^1.1.5",
17
- "@getstrata/core": "^1.1.5",
15
+ "@getstrata/bootstrap": "^1.1.6",
16
+ "@getstrata/cli": "^1.1.6",
17
+ "@getstrata/core": "^1.1.6",
18
18
  "eta": "^4.6.0"
19
19
  },
20
20
  "devDependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/starter",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "Interactive create-strata wizard. Choose each layer; one database engine.",
5
5
  "type": "module",
6
6
  "license": "MIT",