@o3co/create-auth-provider 0.17.0-rc.4 → 0.18.0-rc.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 (110) hide show
  1. package/README.md +2 -198
  2. package/main.js +4 -0
  3. package/package.json +8 -30
  4. package/README.ja.md +0 -200
  5. package/dist/cli.d.mts +0 -3
  6. package/dist/cli.d.mts.map +0 -1
  7. package/dist/cli.mjs +0 -18
  8. package/dist/index.d.mts +0 -48
  9. package/dist/index.d.mts.map +0 -1
  10. package/dist/index.mjs +0 -325
  11. package/dist/internal/template-filter.d.mts +0 -14
  12. package/dist/internal/template-filter.d.mts.map +0 -1
  13. package/dist/internal/template-filter.mjs +0 -42
  14. package/templates/standalone/.dockerignore +0 -23
  15. package/templates/standalone/.env.example +0 -152
  16. package/templates/standalone/Dockerfile +0 -125
  17. package/templates/standalone/Makefile +0 -12
  18. package/templates/standalone/README.ja.md +0 -913
  19. package/templates/standalone/README.md +0 -1537
  20. package/templates/standalone/config/application.conf +0 -351
  21. package/templates/standalone/config/clients.yaml +0 -4
  22. package/templates/standalone/config/clients.yaml.example +0 -118
  23. package/templates/standalone/config/development.conf +0 -17
  24. package/templates/standalone/config/mailpit.conf +0 -13
  25. package/templates/standalone/config/production.conf +0 -15
  26. package/templates/standalone/config/reference.conf +0 -424
  27. package/templates/standalone/docker-compose.mailpit.yml +0 -39
  28. package/templates/standalone/docker-compose.production.yml +0 -229
  29. package/templates/standalone/docker-compose.test.yml +0 -16
  30. package/templates/standalone/docker-compose.yml +0 -67
  31. package/templates/standalone/gitignore +0 -23
  32. package/templates/standalone/package.json +0 -55
  33. package/templates/standalone/src/__tests__/adapters.test.mts +0 -425
  34. package/templates/standalone/src/__tests__/admission-lifecycle.test.mts +0 -87
  35. package/templates/standalone/src/__tests__/all-modules-composition.fixture.mts +0 -1192
  36. package/templates/standalone/src/__tests__/all-modules-composition.multi.test.mts +0 -285
  37. package/templates/standalone/src/__tests__/all-modules-composition.test.mts +0 -1154
  38. package/templates/standalone/src/__tests__/audit-sink.test.mts +0 -346
  39. package/templates/standalone/src/__tests__/config-notices.test.mts +0 -157
  40. package/templates/standalone/src/__tests__/configPath.test.mts +0 -69
  41. package/templates/standalone/src/__tests__/configured-mfa-mode.fixture.mts +0 -48
  42. package/templates/standalone/src/__tests__/core-federations.test.mts +0 -252
  43. package/templates/standalone/src/__tests__/core-sections.test.mts +0 -192
  44. package/templates/standalone/src/__tests__/device-code-store-client-module.test.mts +0 -95
  45. package/templates/standalone/src/__tests__/documented-env-overrides.test.mts +0 -1290
  46. package/templates/standalone/src/__tests__/federation-grants-composition.test.mts +0 -784
  47. package/templates/standalone/src/__tests__/federation-grants-survive-logout.test.mts +0 -461
  48. package/templates/standalone/src/__tests__/federation-token-refresh-outage.test.mts +0 -141
  49. package/templates/standalone/src/__tests__/federation-types.test.mts +0 -239
  50. package/templates/standalone/src/__tests__/google-session.fixture.mts +0 -308
  51. package/templates/standalone/src/__tests__/host-routes.test.mts +0 -134
  52. package/templates/standalone/src/__tests__/library-reference-resolution.smoke.test.mts +0 -29
  53. package/templates/standalone/src/__tests__/library-references.fixture.mts +0 -188
  54. package/templates/standalone/src/__tests__/lifecycle-pending-close.test.mts +0 -216
  55. package/templates/standalone/src/__tests__/listen.test.mts +0 -121
  56. package/templates/standalone/src/__tests__/logger-projection.test.mts +0 -77
  57. package/templates/standalone/src/__tests__/logout-session-cookie.test.mts +0 -113
  58. package/templates/standalone/src/__tests__/mail-sender.test.mts +0 -134
  59. package/templates/standalone/src/__tests__/mailpit-compose.test.mts +0 -393
  60. package/templates/standalone/src/__tests__/metrics.test.mts +0 -253
  61. package/templates/standalone/src/__tests__/mfa-routes-budget.test.mts +0 -122
  62. package/templates/standalone/src/__tests__/mfa-switch.redis.test.mts +0 -127
  63. package/templates/standalone/src/__tests__/mfa-switch.test.mts +0 -883
  64. package/templates/standalone/src/__tests__/own-modules.test.mts +0 -1512
  65. package/templates/standalone/src/__tests__/post-logout-redirect.test.mts +0 -183
  66. package/templates/standalone/src/__tests__/redis-assume-noeviction.test.mts +0 -214
  67. package/templates/standalone/src/__tests__/redis-connection-error-log.test.mts +0 -135
  68. package/templates/standalone/src/__tests__/redis-rate-limiter-config-survives.test.mts +0 -214
  69. package/templates/standalone/src/__tests__/refresh-token-family-client-module.test.mts +0 -249
  70. package/templates/standalone/src/__tests__/replica-safety.test.mts +0 -654
  71. package/templates/standalone/src/__tests__/repositories-logger.test.mts +0 -119
  72. package/templates/standalone/src/__tests__/router-error-answers.test.mts +0 -146
  73. package/templates/standalone/src/__tests__/scaffold-assets.test.mts +0 -610
  74. package/templates/standalone/src/__tests__/sections.test.mts +0 -504
  75. package/templates/standalone/src/__tests__/session-lifecycle.test.mts +0 -215
  76. package/templates/standalone/src/__tests__/session-logout-invalidates-token.test.mts +0 -296
  77. package/templates/standalone/src/__tests__/session-logout-lifecycle.test.mts +0 -130
  78. package/templates/standalone/src/__tests__/session-requirements.test.mts +0 -382
  79. package/templates/standalone/src/__tests__/shipped-config-notices.test.mts +0 -274
  80. package/templates/standalone/src/__tests__/shutdown.test.mts +0 -622
  81. package/templates/standalone/src/__tests__/smoke.test.mts +0 -634
  82. package/templates/standalone/src/__tests__/startup-log-lines.test.mts +0 -148
  83. package/templates/standalone/src/__tests__/store-credential.test.mts +0 -312
  84. package/templates/standalone/src/__tests__/supertest-loopback.test.mts +0 -296
  85. package/templates/standalone/src/__tests__/three-tier-resolution.test.mts +0 -265
  86. package/templates/standalone/src/__tests__/two-phase-config.test.mts +0 -605
  87. package/templates/standalone/src/__tests__/upstream-amr.acceptance.test.mts +0 -382
  88. package/templates/standalone/src/adapters.mts +0 -162
  89. package/templates/standalone/src/app.mts +0 -136
  90. package/templates/standalone/src/bootRefusal.mts +0 -117
  91. package/templates/standalone/src/buildModules.mts +0 -358
  92. package/templates/standalone/src/configPath.mts +0 -487
  93. package/templates/standalone/src/listen.mts +0 -60
  94. package/templates/standalone/src/logger.mts +0 -80
  95. package/templates/standalone/src/metrics.mts +0 -167
  96. package/templates/standalone/src/mfaSwitch.mts +0 -284
  97. package/templates/standalone/src/modules.mts +0 -705
  98. package/templates/standalone/src/rootRenames.mts +0 -95
  99. package/templates/standalone/src/routes.mts +0 -89
  100. package/templates/standalone/src/sections.mts +0 -377
  101. package/templates/standalone/src/shutdown.mts +0 -213
  102. package/templates/standalone/tests/Makefile +0 -5
  103. package/templates/standalone/tests/index.test.js +0 -283
  104. package/templates/standalone/tests/package-lock.json +0 -1617
  105. package/templates/standalone/tests/package.json +0 -16
  106. package/templates/standalone/tests/vitest.config.mjs +0 -26
  107. package/templates/standalone/tsconfig.json +0 -31
  108. package/templates/standalone/vitest.config.mts +0 -31
  109. package/templates/standalone/vitest.supertest-loopback.mts +0 -278
  110. package/templates/versions.json +0 -20
package/dist/index.mjs DELETED
@@ -1,325 +0,0 @@
1
- /*
2
- * Copyright 2026 1o1 Co. Ltd.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- import { spawnSync } from "node:child_process";
17
- import { appendFileSync, cpSync, existsSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
18
- import { dirname, resolve } from "node:path";
19
- import { fileURLToPath } from "node:url";
20
- import { shouldCopyTemplateEntry } from "./internal/template-filter.mjs";
21
- const __dirname = dirname(fileURLToPath(import.meta.url));
22
- const TEMPLATES_ROOT = resolve(__dirname, "../templates");
23
- /** The template a scaffold is made from when none is named. */
24
- export const DEFAULT_TEMPLATE = "standalone";
25
- /**
26
- * The templates under `templatesRoot`: every directory — not a symbolic link,
27
- * not dot-named — holding a `package.json`, sorted; none when the directory is
28
- * missing. This is the rule `scripts/templates.mjs` copies templates by, read
29
- * here from the copy, where `versions.json` sits beside them. A name is only
30
- * ever looked up in this list, so nothing outside the templates directory can
31
- * be named as a template.
32
- */
33
- export const availableTemplates = (templatesRoot = TEMPLATES_ROOT) => {
34
- if (!existsSync(templatesRoot))
35
- return [];
36
- return readdirSync(templatesRoot, { withFileTypes: true })
37
- .filter((entry) => entry.isDirectory() &&
38
- !entry.name.startsWith(".") &&
39
- existsSync(resolve(templatesRoot, entry.name, "package.json")))
40
- .map((entry) => entry.name)
41
- .sort();
42
- };
43
- /**
44
- * Why `template` cannot be scaffolded from `templates`, or `undefined` when it
45
- * can: none is bundled (a checkout that never ran the prebuild script), or it
46
- * is not one of them.
47
- */
48
- export const templateRefusal = (template, templates) => {
49
- if (templates.length === 0) {
50
- return `No templates found at ${TEMPLATES_ROOT}. If developing locally, run the prebuild script first.`;
51
- }
52
- if (!templates.includes(template)) {
53
- return `Unknown template '${template}'. Available templates: ${templates.join(", ")}.`;
54
- }
55
- return undefined;
56
- };
57
- const getPackageVersions = () => {
58
- const versionFile = resolve(__dirname, "../templates/versions.json");
59
- if (existsSync(versionFile)) {
60
- return JSON.parse(readFileSync(versionFile, "utf-8"));
61
- }
62
- return {};
63
- };
64
- const UNSCOPED_NAME_RE = /^[a-z0-9][a-z0-9-._~]*$/;
65
- const SCOPED_NAME_RE = /^@[a-z0-9][a-z0-9-._~]*\/[a-z0-9][a-z0-9-._~]*$/;
66
- const MAX_NAME_LEN = 214;
67
- export const isValidProjectName = (name) => {
68
- if (name.length === 0 || name.length > MAX_NAME_LEN)
69
- return false;
70
- if (name === "." || name === "..")
71
- return false;
72
- return UNSCOPED_NAME_RE.test(name) || SCOPED_NAME_RE.test(name);
73
- };
74
- export const isValidDirName = (name) => {
75
- if (name.length === 0 || name.length > MAX_NAME_LEN)
76
- return false;
77
- if (name === "." || name === "..")
78
- return false;
79
- return UNSCOPED_NAME_RE.test(name);
80
- };
81
- /**
82
- * Appended to the scaffold's `config/application.conf` by `noMfa`: the
83
- * template's switch `mfaMode` written off, then bound to `MFA_MODE` so the
84
- * variable wins over the written value. The MFA package stays a dependency.
85
- */
86
- const MFA_OFF_LINES = [
87
- "",
88
- "# written by create-app --no-mfa: MFA is off unless MFA_MODE turns it on",
89
- 'mfaMode = "off"',
90
- // biome-ignore lint/suspicious/noTemplateCurlyInString: a HOCON substitution, not a template
91
- "mfaMode = ${?MFA_MODE}",
92
- ];
93
- export const scaffold = (targetDir, projectName, template = DEFAULT_TEMPLATE, options = {}) => {
94
- const refusal = templateRefusal(template, availableTemplates());
95
- if (refusal !== undefined)
96
- throw new Error(refusal);
97
- const templateDir = resolve(TEMPLATES_ROOT, template);
98
- // Copy template to target
99
- cpSync(templateDir, targetDir, {
100
- recursive: true,
101
- filter: (source) => shouldCopyTemplateEntry(source, templateDir),
102
- });
103
- // npm drops a file literally named `.gitignore` from a published package,
104
- // so `copy-templates.mjs` stages it dot-less and it is restored here.
105
- // Without it the first `git add .` in a scaffolded project commits the
106
- // `.env` and the signing key the README's setup steps create.
107
- const stagedGitignore = resolve(targetDir, "gitignore");
108
- if (existsSync(stagedGitignore)) {
109
- renameSync(stagedGitignore, resolve(targetDir, ".gitignore"));
110
- }
111
- if (options.noMfa === true) {
112
- appendFileSync(resolve(targetDir, "config", "application.conf"), `${MFA_OFF_LINES.join("\n")}\n`);
113
- }
114
- // Rewrite package.json
115
- const pkgPath = resolve(targetDir, "package.json");
116
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
117
- pkg.name = projectName;
118
- // `"private": true` is deliberately kept: the scaffold is an identity
119
- // provider (keys, config, policy), so an accidental `npm publish` must fail
120
- // by default. An operator who means to publish removes the field.
121
- // o3co/auth.policy-verifier's scaffolder does the same; change the two together.
122
- // Replace all workspace:* references with per-package published versions
123
- const versions = getPackageVersions();
124
- for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
125
- const deps = pkg[section];
126
- if (!deps)
127
- continue;
128
- for (const [name, version] of Object.entries(deps)) {
129
- if (version === "workspace:*") {
130
- const resolved = versions[name];
131
- if (!resolved) {
132
- throw new Error(`Cannot resolve version for workspace dependency "${name}". Ensure versions.json includes this package.`);
133
- }
134
- deps[name] = `^${resolved}`;
135
- }
136
- }
137
- }
138
- writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
139
- // pnpm ≥10.29 reads `onlyBuiltDependencies` only from pnpm-workspace.yaml,
140
- // even in single-package projects. The template cannot ship the file:
141
- // inside the monorepo it would shadow the workspace root. So the scaffold
142
- // writes it, mirroring the workspace root's allowlist.
143
- writeFileSync(resolve(targetDir, "pnpm-workspace.yaml"), [
144
- "# pnpm (>= 10.29) reads onlyBuiltDependencies from this file, even in a",
145
- "# single-package project. bcrypt's install hook compiles the native addon",
146
- "# on platforms with no shipped prebuild; without this allowlist pnpm",
147
- "# silently skips the hook and bcrypt fails at require time there.",
148
- "onlyBuiltDependencies:",
149
- " - bcrypt",
150
- "",
151
- ].join("\n"));
152
- };
153
- /**
154
- * `--lockfile-only` resolves the dependency graph without installing or
155
- * running any script. `--ignore-workspace` keeps the new project's lockfile
156
- * its own even when the target directory happens to sit inside somebody
157
- * else's pnpm workspace.
158
- */
159
- const LOCKFILE_ARGS = ["install", "--lockfile-only", "--ignore-workspace"];
160
- /**
161
- * Launchers tried in order: `pnpm` on PATH, then `corepack pnpm` for a machine
162
- * with Node's bundled corepack but no global pnpm. Only ENOENT falls through to
163
- * the next launcher; a non-zero exit would fail identically through any of
164
- * them, and other launch errors surface as themselves.
165
- */
166
- const LOCKFILE_LAUNCHERS = [["pnpm"], ["corepack", "pnpm"]];
167
- /**
168
- * Resolve the scaffolded project's dependency graph into `pnpm-lock.yaml`,
169
- * which the template's `pnpm install --frozen-lockfile` build needs. The
170
- * lockfile cannot ship with the template: the dependency set it pins exists
171
- * only after `scaffold` has replaced every `workspace:*`. Best-effort (it needs
172
- * a package manager and a reachable registry), so failure is a result, not a
173
- * throw.
174
- */
175
- export const generateLockfile = (targetDir) => {
176
- const attempts = [];
177
- for (const launcher of LOCKFILE_LAUNCHERS) {
178
- const [bin, ...prefix] = launcher;
179
- const args = [...prefix, ...LOCKFILE_ARGS];
180
- const printable = [bin, ...args].join(" ");
181
- const result = spawnSync(bin, args, {
182
- cwd: targetDir,
183
- stdio: "inherit",
184
- shell: false,
185
- env: { ...process.env, COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
186
- });
187
- if (result.error) {
188
- attempts.push(`${printable}: ${result.error.message}`);
189
- // Only "not on PATH" is worth asking a different launcher about.
190
- if (result.error.code === "ENOENT")
191
- continue;
192
- break;
193
- }
194
- if (result.status === 0)
195
- return { ok: true, command: printable };
196
- const how = result.status === null ? `killed by signal ${result.signal}` : `exit code ${result.status}`;
197
- attempts.push(`${printable}: ${how}`);
198
- break;
199
- }
200
- return { ok: false, reason: attempts.join("; ") };
201
- };
202
- /** The flags that take a value, as `--flag <value>` or `--flag=<value>`. */
203
- const VALUE_FLAGS = ["--dir", "--template"];
204
- const parseArgs = (args) => {
205
- const positionals = [];
206
- const values = new Map();
207
- let lockfile = true;
208
- let noMfa = false;
209
- const setValue = (flag, value) => {
210
- if (values.has(flag))
211
- throw new Error(`${flag} specified more than once`);
212
- if (value === "")
213
- throw new Error(`${flag} requires a value`);
214
- values.set(flag, value);
215
- };
216
- for (let i = 0; i < args.length; i++) {
217
- const a = args[i];
218
- const spaced = VALUE_FLAGS.find((flag) => a === flag);
219
- const joined = VALUE_FLAGS.find((flag) => a.startsWith(`${flag}=`));
220
- if (spaced !== undefined) {
221
- if (i + 1 >= args.length)
222
- throw new Error(`${spaced} requires a value`);
223
- setValue(spaced, args[i + 1]);
224
- i++;
225
- }
226
- else if (joined !== undefined) {
227
- setValue(joined, a.slice(`${joined}=`.length));
228
- }
229
- else if (a === "--no-lockfile") {
230
- lockfile = false;
231
- }
232
- else if (a === "--no-mfa") {
233
- noMfa = true;
234
- }
235
- else if (a.startsWith("-")) {
236
- // Treats `--` and any --unknown as an unknown flag.
237
- throw new Error(`unknown flag: ${a}`);
238
- }
239
- else {
240
- positionals.push(a);
241
- }
242
- }
243
- if (positionals.length === 0)
244
- throw new Error("missing <project-name>");
245
- if (positionals.length > 1)
246
- throw new Error("too many positional arguments");
247
- return {
248
- projectName: positionals[0],
249
- dir: values.get("--dir"),
250
- template: values.get("--template"),
251
- lockfile,
252
- noMfa,
253
- };
254
- };
255
- const deriveDirName = (projectName, dir) => {
256
- if (dir !== undefined)
257
- return dir;
258
- if (projectName.startsWith("@")) {
259
- const pkgPart = projectName.split("/")[1];
260
- if (!pkgPart) {
261
- // Unreachable when projectName has passed isValidProjectName (SCOPED_NAME_RE
262
- // guarantees a non-empty package segment after the single "/"). Guarded here
263
- // so refactors that reorder validation cannot silently produce undefined.
264
- throw new Error(`invariant: unvalidated scoped name ${projectName}`);
265
- }
266
- return pkgPart;
267
- }
268
- return projectName;
269
- };
270
- // CLI entry point
271
- export const main = () => {
272
- const args = process.argv.slice(2);
273
- let parsed;
274
- try {
275
- parsed = parseArgs(args);
276
- }
277
- catch (e) {
278
- console.error(`Error: ${e.message}`);
279
- console.error("Usage: @o3co/create-auth-provider <project-name> [--template <name>] [--dir <dir-name>] [--no-lockfile] [--no-mfa]");
280
- console.error("<project-name> must be a valid npm package name (scoped like @scope/pkg, or unscoped).");
281
- console.error(`--template names the template to copy (default: ${DEFAULT_TEMPLATE}); available: ${availableTemplates().join(", ")}.`);
282
- process.exit(1);
283
- }
284
- const { projectName, dir, lockfile, noMfa } = parsed;
285
- const template = parsed.template ?? DEFAULT_TEMPLATE;
286
- if (!isValidProjectName(projectName)) {
287
- console.error("Error: <project-name> must be a valid npm package name (scoped like @scope/pkg, or unscoped; max 214 chars; no backslashes; no extra '/' beyond the single scope separator).");
288
- process.exit(1);
289
- }
290
- if (dir !== undefined && !isValidDirName(dir)) {
291
- console.error("Error: --dir must be a valid unscoped package name (no '/', '\\', '@'; not '.' or '..'; max 214 chars).");
292
- process.exit(1);
293
- }
294
- const refusal = templateRefusal(template, availableTemplates());
295
- if (refusal !== undefined) {
296
- console.error(`Error: ${refusal}`);
297
- process.exit(1);
298
- }
299
- const dirName = deriveDirName(projectName, dir);
300
- const targetDir = resolve(process.cwd(), dirName);
301
- if (existsSync(targetDir)) {
302
- console.error(`Error: Directory '${dirName}' already exists.`);
303
- process.exit(1);
304
- }
305
- console.log(`Creating ${projectName} from the ${template} template...`);
306
- scaffold(targetDir, projectName, template, { noMfa });
307
- let lockfileGenerated = false;
308
- if (lockfile) {
309
- console.log("\nResolving dependencies into pnpm-lock.yaml...");
310
- const result = generateLockfile(targetDir);
311
- lockfileGenerated = result.ok;
312
- if (!result.ok) {
313
- console.error(`\nWarning: could not generate pnpm-lock.yaml (${result.reason}).`);
314
- console.error(`Run 'pnpm install' in ${dirName} and commit pnpm-lock.yaml: the Dockerfile installs with --frozen-lockfile and will not build without it.`);
315
- }
316
- }
317
- console.log(`\nDone! Created ${projectName} at ${targetDir}`);
318
- if (lockfileGenerated) {
319
- console.log("\nCommit pnpm-lock.yaml along with the rest: it is what makes 'docker build' reproducible.");
320
- }
321
- console.log(`\nNext steps:`);
322
- console.log(` cd ${dirName}`);
323
- console.log(" pnpm install");
324
- console.log(" pnpm run debug");
325
- };
@@ -1,14 +0,0 @@
1
- /**
2
- * Decide whether `cpSync` should copy a given source path.
3
- *
4
- * Only segments inside `templateRoot` are checked against EXCLUDED_DIRS; the
5
- * install prefix above it (e.g. `~/.npm/_npx/<hash>/node_modules/...` under
6
- * `npx`) is ignored, or every file would be rejected whenever the package
7
- * itself lives under a `node_modules` directory.
8
- *
9
- * `pathSep` lets tests exercise POSIX and Windows separators on any host.
10
- * Production callers keep the `path.sep` default: `cpSync` passes
11
- * backslash-delimited paths on Windows.
12
- */
13
- export declare const shouldCopyTemplateEntry: (source: string, templateRoot: string, pathSep?: string) => boolean;
14
- //# sourceMappingURL=template-filter.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"template-filter.d.mts","sourceRoot":"","sources":["../../src/internal/template-filter.mts"],"names":[],"mappings":"AAuBA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GACnC,QAAQ,MAAM,EACd,cAAc,MAAM,EACpB,UAAS,MAAY,KACnB,OAMF,CAAC"}
@@ -1,42 +0,0 @@
1
- /*
2
- * Copyright 2026 1o1 Co. Ltd.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- //
17
- // INTERNAL — not exposed via the package's `exports` map. Reachable only from
18
- // other files in this package (and its tests). See package.json `exports`.
19
- //
20
- import { sep } from "node:path";
21
- const EXCLUDED_DIRS = new Set(["node_modules", "dist"]);
22
- /**
23
- * Decide whether `cpSync` should copy a given source path.
24
- *
25
- * Only segments inside `templateRoot` are checked against EXCLUDED_DIRS; the
26
- * install prefix above it (e.g. `~/.npm/_npx/<hash>/node_modules/...` under
27
- * `npx`) is ignored, or every file would be rejected whenever the package
28
- * itself lives under a `node_modules` directory.
29
- *
30
- * `pathSep` lets tests exercise POSIX and Windows separators on any host.
31
- * Production callers keep the `path.sep` default: `cpSync` passes
32
- * backslash-delimited paths on Windows.
33
- */
34
- export const shouldCopyTemplateEntry = (source, templateRoot, pathSep = sep) => {
35
- if (source === templateRoot)
36
- return true;
37
- const prefix = templateRoot.endsWith(pathSep) ? templateRoot : `${templateRoot}${pathSep}`;
38
- if (!source.startsWith(prefix))
39
- return true;
40
- const rel = source.slice(prefix.length);
41
- return !rel.split(pathSep).some((s) => EXCLUDED_DIRS.has(s));
42
- };
@@ -1,23 +0,0 @@
1
- node_modules
2
- dist
3
- .git
4
- Makefile
5
- # #705: the secrets and the per-deployment configuration that `.gitignore`
6
- # keeps out of git stay out of the build context as well. The builder stage
7
- # COPYs `config/` and the runtime image takes it from there, so a
8
- # `config/clients.yaml` in the working copy — client secrets included — was
9
- # baked into a layer that travels with every push; the production compose
10
- # mounts the registry instead. This is `.gitignore`'s secrets section, written
11
- # with `**/` where it matches at any depth: a `.dockerignore` pattern is
12
- # anchored at the context root. Keep the two in step; scaffold-assets.test.mts
13
- # checks that they are.
14
- **/.env*
15
- !**/.env.example
16
- **/*.pem
17
- **/*.key
18
- config/clients.yaml
19
- config/*.local.conf
20
- # .gitignore, the READMEs and the compose files stay in the context: the
21
- # `test` image copies them because the shipped suite reads them (#512). The
22
- # runtime image never copies them, so they cost the context a few kilobytes
23
- # and the image nothing.
@@ -1,152 +0,0 @@
1
- # Canonical issuer stamped as `iss` on every token this deployment mints.
2
- # Absolute https URL (http only for a loopback host), no query or fragment.
3
- # Boot fails when unset — it is never derived from the Host header.
4
- OAUTH_JWT_ISSUER=
5
-
6
- # --- JWT signing key (required) ---------------------------------------------
7
- # The default algorithm is EdDSA (Ed25519). There is no key-material default:
8
- # a deployment that sets none fails at boot naming the keys to set, rather than
9
- # quietly signing with something guessable.
10
- #
11
- # openssl genpkey -algorithm ed25519 -out jwt-private.pem
12
- # openssl pkey -in jwt-private.pem -pubout -out jwt-public.pem
13
- #
14
- # Keep jwt-private.pem out of version control and off the image.
15
- KEY_STORE_LOCAL_PRIVATE_KEY_PATH=./jwt-private.pem
16
- KEY_STORE_LOCAL_PUBLIC_KEY_PATH=./jwt-public.pem
17
- # KEY_STORE_LOCAL_ALGORITHM=EdDSA # EdDSA | ES256 | RS256 | HS256
18
- # KEY_STORE_LOCAL_KID=v0
19
- #
20
- # HS256 alternative — symmetric, so /.well-known/jwks.json publishes NOTHING
21
- # and every relying party must hold a secret that can also MINT tokens. Only
22
- # for deployments that verify in-process. Needs >= 32 bytes (256 bits):
23
- # openssl rand -hex 32
24
- # Hex/base64 values are measured DECODED, so a 32-character hex string counts
25
- # as 16 bytes and is refused.
26
- # KEY_STORE_LOCAL_ALGORITHM=HS256
27
- # KEY_STORE_LOCAL_SECRET=
28
-
29
- # --- Session (required) ------------------------------------------------------
30
- # Signs the cookie that IS the authenticated session, so guessing it forges
31
- # logins. Same >= 32-byte floor and same decoded measurement:
32
- # openssl rand -hex 32
33
- SESSION_STORE_SECRET=
34
-
35
- # User repository
36
- # Both URLs carry plaintext user credentials to the upstream store, so both must
37
- # be absolute https URLs. http:// is accepted only for a loopback host
38
- # (localhost, 127.0.0.0/8, [::1]) — a private-range address or a compose service
39
- # name such as http://user-service:8080 still needs https. Boot fails otherwise.
40
- # Each must be the endpoint that answers: no request follows a 3xx, so a URL that
41
- # redirects fails every call.
42
- REPOSITORIES_USER_HTTP_AUTHENTICATE_URL=
43
- REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL=
44
- # With MFA on: the Store's endpoint the MFA enrollment witness is written to,
45
- # so a Store that loses a subject's factors cannot open a first binding to
46
- # whoever holds the password. Your Store must then answer `mfaEnrolled` on
47
- # both URLs above. Unset, boot warns (mfa_enrollment_witness_unwritable).
48
- # REPOSITORIES_USER_HTTP_MARK_MFA_ENROLLED_URL=https://users.example.com/mfa/enrolled
49
- # The credential this server presents to the Store: every Store request carries
50
- # `Authorization: Bearer <token>`. Without one, anyone who can reach the Store
51
- # can resolve an identity to its user, so your Store should refuse any request
52
- # without it, with 401 and `WWW-Authenticate: Bearer error="invalid_token"`
53
- # (which this server then reports as an outage naming the refused credential).
54
- # The one token goes to every Store URL above: they must be one trust domain.
55
- # At least 32 bytes, measured like SESSION_STORE_SECRET; boot fails on a weak or
56
- # malformed value. Left commented out because a blank value is refused too:
57
- # openssl rand -hex 32
58
- # REPOSITORIES_USER_HTTP_BEARER_TOKEN=
59
-
60
- # --- Reverse proxy (required in production) -----------------------------------
61
- # Express `trust proxy`. Set this to the address or CIDR range of whatever
62
- # terminates TLS in front of this service — `10.0.0.0/8`, or `loopback` for a
63
- # sidecar on the same host. Comma-separate several.
64
- #
65
- # Prefer naming the hop over `true`: `true` believes a forwarded client address
66
- # from anyone who can reach this process, and with it any rate-limit identity.
67
- # Left EMPTY here because it cannot be guessed; `docker-compose.production.yml`
68
- # refuses to start until it is set, since without it the Secure cookie is never
69
- # set, the CSRF origin check 403s every browser POST, and every IP-keyed rate
70
- # limit shares one bucket. A plain-HTTP local run needs nothing here.
71
- HTTP_TRUST_PROXY=
72
-
73
- # Redis (session storage + the shared client socket)
74
- # Use redis://redis:6379 when running via docker compose
75
- SESSION_STORE_STORAGE_REDIS_URL=redis://redis:6379
76
- # #407: this one backs the SHARED ioredis socket -- the refresh-token family
77
- # store, the access-token denylist and the rate limiter all ride on it. It
78
- # defaults to redis://localhost:6379, which inside the container is the
79
- # container, so leaving it unset makes the compose boot dial nothing.
80
- REDIS_CLIENTS_URL=redis://redis:6379
81
- # The Redis stores refuse to boot unless the server reports maxmemory-policy
82
- # noeviction (README: Multi-replica deployments). Only for a server that does
83
- # run noeviction but will not report it (INFO and CONFIG refused to this user):
84
- # REDIS_CLIENTS_ASSUME_NO_EVICTION=true
85
-
86
- # --- Federation grants (#593, optional) --------------------------------------
87
- # Offline delegation of an upstream IdP's tokens to a backend or an agent, on a
88
- # consent that survives logout. Off by default; on, boot refuses what is
89
- # missing by name. The consent page is yours (README: Federation Grants). The
90
- # connections and the encryption key ring are lists, so they live in a HOCON
91
- # layer, not here. Both stores ship as none: select each (redis, or memory on
92
- # one replica) with the two ADAPTERS_ lines below. Redis GRANTS need
93
- # ADAPTERS_USER_SESSION_STORES=redis beside them (the compose files set it) —
94
- # the grants would outlive a memory boundary that ends them.
95
- # FEDERATION_GRANTS_ENABLED=true
96
- # FEDERATION_GRANTS_CONSENT_URL=/consent/grants
97
- # `required` seals credentials under redis-federation-grant-store.encryptionKeys (HOCON);
98
- # `allow-plaintext` is refused in production/staging and under multi.
99
- # REDIS_FEDERATION_GRANT_STORE_ENCRYPTION_MODE=required
100
- # `required` needs a user repository that covers every connection's
101
- # registration: the shipped http one asks your Store at the URL below and
102
- # covers what repositories.user.http.federatedIdentityLookupCoverage (HOCON)
103
- # declares; `unsupported` records that the check is not made.
104
- # FEDERATION_GRANTS_IDENTITY_LOOKUP=required
105
- # REPOSITORIES_USER_HTTP_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL=https://users.example.com/find-subject-by-federated-identity
106
- # ADAPTERS_FEDERATION_GRANT_STORE=redis
107
- # ADAPTERS_FEDERATION_GRANT_INTENT_STORE=redis
108
-
109
- # --- Multi-factor authentication (on by default) -----------------------------
110
- # MFA_MODE: required (the default: every password login needs a second
111
- # factor) | optional | off. The MFA page is yours (README: Multi-factor
112
- # authentication). Development needs nothing here: config/development.conf
113
- # holds a sample key, the codes are logged, and docker-compose.yml keeps the
114
- # two MFA stores on its Redis. Outside development, set all of the following,
115
- # or boot is refused naming them:
116
- # - the two MFA stores, which ship in memory, refused outside development and
117
- # test since a restart empties them of every factor: redis (or, for the
118
- # factors, store);
119
- # - a key of your own (openssl rand -base64 32);
120
- # - the SMTP relay the account-email proof and the email factor's codes go
121
- # through.
122
- # The MFA page's URL defaults to /mfa, which you must serve, in development
123
- # too, or every password login stops there.
124
- # ADAPTERS_MFA_FACTOR_STORE=redis
125
- # ADAPTERS_MFA_TRANSACTION_STORE=redis
126
- # MFA_ENCRYPTION_KEY=
127
- # STANDARD_SMTP_MAIL_SENDER_HOST=smtp.example.com
128
- # STANDARD_SMTP_MAIL_SENDER_FROM=auth@example.com
129
- # MFA_PAGE_URL=/mfa
130
- # Or run without MFA:
131
- # MFA_MODE=off
132
- # To read the mail in development, leave every STANDARD_SMTP_MAIL_SENDER_*
133
- # unset (USER and PASSWORD included), set MFA_ENCRYPTION_KEY to a key of your
134
- # own (the run does not use the development sample key), and run the Mailpit
135
- # overlay, which sets the sender's variables (README: Mailpit for the SMTP sender):
136
- # docker compose -f docker-compose.yml -f docker-compose.mailpit.yml up --build
137
-
138
- # Development (override for local HTTP).
139
- # The default cookie name carries the `__Host-` prefix, which browsers only
140
- # accept on a Secure cookie — so dropping Secure means renaming the cookie too,
141
- # or boot refuses the combination.
142
- SESSION_STORE_SECURE=false
143
- SESSION_STORE_NAME=auth.sid
144
-
145
- # Optional
146
- # HTTP_PORT=3000
147
- # OAUTH_ACCESS_TOKEN_DEFAULT_EXPIRES_IN=3600
148
- # The most a token-exchange `expires_in` can obtain; unset = the default.
149
- # OAUTH_ACCESS_TOKEN_MAX_EXPIRES_IN=3600
150
- # OAUTH_REFRESH_TOKEN_EXPIRES_IN=86400
151
- # SESSION_STORE_MAX_AGE=3600000
152
- # SESSION_STORE_SAME_SITE=lax # `none` additionally requires SESSION_STORE_SECURE=true