@we8/cloudflare 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +99 -6
  2. package/dist/access.d.ts +129 -0
  3. package/dist/access.d.ts.map +1 -0
  4. package/dist/access.js +211 -0
  5. package/dist/access.js.map +1 -0
  6. package/dist/admin-auth.d.ts +42 -0
  7. package/dist/admin-auth.d.ts.map +1 -0
  8. package/dist/admin-auth.js +19 -0
  9. package/dist/admin-auth.js.map +1 -0
  10. package/dist/cli-args.d.ts +8 -2
  11. package/dist/cli-args.d.ts.map +1 -1
  12. package/dist/cli-args.js +28 -4
  13. package/dist/cli-args.js.map +1 -1
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +89 -6
  17. package/dist/cli.js.map +1 -1
  18. package/dist/doctor.d.ts +79 -3
  19. package/dist/doctor.d.ts.map +1 -1
  20. package/dist/doctor.js +250 -15
  21. package/dist/doctor.js.map +1 -1
  22. package/dist/index.d.ts +21 -9
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +20 -9
  25. package/dist/index.js.map +1 -1
  26. package/dist/jwt.d.ts +103 -0
  27. package/dist/jwt.d.ts.map +1 -0
  28. package/dist/jwt.js +265 -0
  29. package/dist/jwt.js.map +1 -0
  30. package/dist/perimeter.d.ts +49 -0
  31. package/dist/perimeter.d.ts.map +1 -0
  32. package/dist/perimeter.js +54 -0
  33. package/dist/perimeter.js.map +1 -0
  34. package/dist/project.d.ts +7 -0
  35. package/dist/project.d.ts.map +1 -1
  36. package/dist/project.js +31 -0
  37. package/dist/project.js.map +1 -1
  38. package/dist/skill-command.d.ts +48 -0
  39. package/dist/skill-command.d.ts.map +1 -0
  40. package/dist/skill-command.js +122 -0
  41. package/dist/skill-command.js.map +1 -0
  42. package/dist/skill.d.ts +51 -0
  43. package/dist/skill.d.ts.map +1 -0
  44. package/dist/skill.js +229 -0
  45. package/dist/skill.js.map +1 -0
  46. package/dist/wrangler-config.d.ts +64 -1
  47. package/dist/wrangler-config.d.ts.map +1 -1
  48. package/dist/wrangler-config.js +133 -21
  49. package/dist/wrangler-config.js.map +1 -1
  50. package/package.json +2 -2
@@ -0,0 +1,122 @@
1
+ /**
2
+ * `we8-cloudflare skill`: write or refresh the project skill in place.
3
+ *
4
+ * The scaffolder writes the skill once, at `npm create we8`. Everything after
5
+ * that is this command's job: a project that predates the skill adopts one, a
6
+ * project whose auth registration changed refreshes it, and CI checks that the
7
+ * file in the repository is the one this version of the pack would write.
8
+ *
9
+ * The state it generates from is derived from the project itself, never asked
10
+ * for. The mode comes out of the worker entry with its comments stripped (the
11
+ * same read the doctor does, for the same reason: the generated entries
12
+ * explain the modes they are not in), the site workspace is a directory that
13
+ * either exists or does not, and the perimeter acknowledgement is a fact about
14
+ * one line of code. Nothing here can produce a skill that describes a project
15
+ * other than this one.
16
+ */
17
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
18
+ import { dirname, join, resolve } from 'node:path';
19
+ import { findD1Binding, readAdminAuthMode, readPerimeterAcknowledged, } from './doctor.js';
20
+ import { findConfigPath, readWorkerEntry } from './project.js';
21
+ import { parseJsonc } from './jsonc.js';
22
+ import { generateSkill, SKILL_RELATIVE_PATH } from './skill.js';
23
+ /** Whether a directory carries the Astro starter the template scaffolds. */
24
+ export function hasSiteWorkspace(projectDir) {
25
+ return existsSync(join(projectDir, 'site', 'package.json'));
26
+ }
27
+ /**
28
+ * The project's own wrangler config, parsed, or null when this is not a we8
29
+ * project. "Not a we8 project" is a config that is absent, unparseable, or
30
+ * carries no D1 binding named DB: that binding is the shape every command in
31
+ * this pack reads, so a directory without one is somewhere the skill would be
32
+ * a guess rather than a description.
33
+ */
34
+ function readProjectConfig(projectDir) {
35
+ const configPath = findConfigPath(projectDir);
36
+ if (!configPath) {
37
+ return {
38
+ refusal: 'this is not a we8 project: no wrangler.jsonc, wrangler.json, or wrangler.toml here',
39
+ fix: 'Run this from the project root, or scaffold one with: npm create we8',
40
+ };
41
+ }
42
+ if (configPath.endsWith('.toml')) {
43
+ return {
44
+ refusal: `${configPath} is TOML; this pack generates and reads wrangler.jsonc`,
45
+ fix: 'Convert the config to wrangler.jsonc, which is what npm create we8 writes',
46
+ };
47
+ }
48
+ let config;
49
+ try {
50
+ config = parseJsonc(readFileSync(configPath, 'utf8'));
51
+ }
52
+ catch (error) {
53
+ return {
54
+ refusal: `${configPath} could not be parsed: ${error instanceof Error ? error.message : String(error)}`,
55
+ fix: 'Fix the JSON in the config, then run this again',
56
+ };
57
+ }
58
+ if (!findD1Binding(config)) {
59
+ return {
60
+ refusal: 'this is not a we8 project: the wrangler config has no D1 binding named DB',
61
+ fix: 'Run this from a we8 project root, or scaffold one with: npm create we8',
62
+ };
63
+ }
64
+ return { config };
65
+ }
66
+ /**
67
+ * Writes the skill, or checks it. `check` never touches the filesystem beyond
68
+ * reading, so it is safe to run anywhere, CI included.
69
+ */
70
+ export function runSkillCommand(projectDir, options) {
71
+ const dir = resolve(projectDir);
72
+ const path = join(dir, SKILL_RELATIVE_PATH);
73
+ const project = readProjectConfig(dir);
74
+ if ('refusal' in project) {
75
+ return { status: 'not-a-project', path, mode: null, message: project.refusal, fix: project.fix };
76
+ }
77
+ const entry = readWorkerEntry(dir, project.config);
78
+ const mode = readAdminAuthMode(entry);
79
+ const wanted = generateSkill({
80
+ mode,
81
+ site: hasSiteWorkspace(dir),
82
+ ...(mode === 'perimeter' ? { acknowledged: readPerimeterAcknowledged(entry) } : {}),
83
+ });
84
+ const existing = existsSync(path) ? readFileSync(path, 'utf8') : null;
85
+ if (options.check) {
86
+ if (existing === null) {
87
+ return {
88
+ status: 'missing',
89
+ path,
90
+ mode,
91
+ message: `no skill at ${SKILL_RELATIVE_PATH}`,
92
+ fix: 'we8-cloudflare skill',
93
+ };
94
+ }
95
+ if (existing !== wanted) {
96
+ return {
97
+ status: 'stale',
98
+ path,
99
+ mode,
100
+ message: `${SKILL_RELATIVE_PATH} is not what this project would generate (admin auth: ${mode})`,
101
+ fix: 'we8-cloudflare skill',
102
+ };
103
+ }
104
+ return { status: 'current', path, mode, message: `${SKILL_RELATIVE_PATH} is current (admin auth: ${mode})` };
105
+ }
106
+ if (existing === wanted) {
107
+ return { status: 'unchanged', path, mode, message: `${SKILL_RELATIVE_PATH} is already current (admin auth: ${mode})` };
108
+ }
109
+ mkdirSync(dirname(path), { recursive: true });
110
+ writeFileSync(path, wanted, 'utf8');
111
+ return {
112
+ status: 'written',
113
+ path,
114
+ mode,
115
+ message: `${existing === null ? 'Wrote' : 'Refreshed'} ${SKILL_RELATIVE_PATH} (admin auth: ${mode})`,
116
+ };
117
+ }
118
+ /** Zero when the project is in the state the command asked for, one otherwise. */
119
+ export function skillExitCode(status) {
120
+ return status === 'written' || status === 'unchanged' || status === 'current' ? 0 : 1;
121
+ }
122
+ //# sourceMappingURL=skill-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-command.js","sourceRoot":"","sources":["../src/skill-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The project skill, generated.
3
+ *
4
+ * Claude Code and its kin discover a skill at `.claude/skills/<name>/SKILL.md`
5
+ * automatically, so a we8 project can arrive with an agent that already knows
6
+ * how to drive it instead of rediscovering it from the file tree. The file is
7
+ * an operating manual rather than a description: dense, imperative, and true
8
+ * of THIS project, which is why it is generated from the project's own state
9
+ * rather than copied from a fixture.
10
+ *
11
+ * It lives here rather than in `create-we8` because two commands write it:
12
+ * the scaffolder, at `npm create we8`, and `we8-cloudflare skill`, which
13
+ * adopts or refreshes it in a project that already exists. `create-we8`
14
+ * already depends on this package, so one generator serves both with no cycle
15
+ * and no second copy to drift.
16
+ *
17
+ * Everything below is a pure function of the options. The filesystem half is
18
+ * in skill-command.ts.
19
+ */
20
+ import type { AdminAuthMode } from './doctor.js';
21
+ /** Where the skill goes inside a project. Claude Code looks here by itself. */
22
+ export declare const SKILL_RELATIVE_PATH = ".claude/skills/we8/SKILL.md";
23
+ /**
24
+ * Which auth mode the skill teaches. The same vocabulary the doctor reads out
25
+ * of a worker entry, so the skill a project gets and the mode the doctor
26
+ * reports can never disagree: both come from `readAdminAuthMode`.
27
+ *
28
+ * Note that `none` here means what it means everywhere else in this pack, a
29
+ * worker with NO provider registered, and not the scaffolder's `--auth none`,
30
+ * which composes perimeter mode. `create-we8` maps its own answer across.
31
+ */
32
+ export type SkillAuthMode = AdminAuthMode;
33
+ /** What the skill is generated from: the project's state, and nothing else. */
34
+ export interface SkillOptions {
35
+ /** The composed admin auth mode. */
36
+ mode: SkillAuthMode;
37
+ /** True when the project carries the Astro starter under `site/`. */
38
+ site: boolean;
39
+ /**
40
+ * Perimeter mode only: whether the registration says `{ acknowledged: true }`.
41
+ * An unacknowledged perimeter fails `doctor --remote`, so the skill says so.
42
+ */
43
+ acknowledged?: boolean;
44
+ }
45
+ /**
46
+ * The skill, as a string. One argument set in, one file out; no filesystem, no
47
+ * project name, nothing that would make two projects in the same mode disagree
48
+ * about how a we8 site is operated.
49
+ */
50
+ export declare function generateSkill(options: SkillOptions): string;
51
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;AAE1C,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,IAAI,EAAE,aAAa,CAAC;IACpB,qEAAqE;IACrE,IAAI,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA+FD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CA+G3D"}
package/dist/skill.js ADDED
@@ -0,0 +1,229 @@
1
+ /**
2
+ * The project skill, generated.
3
+ *
4
+ * Claude Code and its kin discover a skill at `.claude/skills/<name>/SKILL.md`
5
+ * automatically, so a we8 project can arrive with an agent that already knows
6
+ * how to drive it instead of rediscovering it from the file tree. The file is
7
+ * an operating manual rather than a description: dense, imperative, and true
8
+ * of THIS project, which is why it is generated from the project's own state
9
+ * rather than copied from a fixture.
10
+ *
11
+ * It lives here rather than in `create-we8` because two commands write it:
12
+ * the scaffolder, at `npm create we8`, and `we8-cloudflare skill`, which
13
+ * adopts or refreshes it in a project that already exists. `create-we8`
14
+ * already depends on this package, so one generator serves both with no cycle
15
+ * and no second copy to drift.
16
+ *
17
+ * Everything below is a pure function of the options. The filesystem half is
18
+ * in skill-command.ts.
19
+ */
20
+ /** Where the skill goes inside a project. Claude Code looks here by itself. */
21
+ export const SKILL_RELATIVE_PATH = '.claude/skills/we8/SKILL.md';
22
+ /** How the auth section heads itself, per mode. */
23
+ const MODE_HEADING = {
24
+ embedded: 'Auth: embedded mode',
25
+ access: 'Auth: access mode',
26
+ perimeter: 'Auth: perimeter mode',
27
+ external: 'Auth: an external provider',
28
+ none: 'Auth: no provider registered',
29
+ unknown: 'Auth: mode unverified',
30
+ };
31
+ /** The mode-specific half of the auth section. */
32
+ function authSection(options, p) {
33
+ switch (options.mode) {
34
+ case 'embedded':
35
+ p('- @we8/auth is registered: Better Auth over this site\'s own D1, mounted at');
36
+ p(' /api/auth/*, email and password.');
37
+ p('- The FIRST sign-up becomes the owner and public sign-up closes behind it.');
38
+ p(' Every account after that is created BY the owner, in the portal under');
39
+ p(' Setup or at POST /v1/admin/users. Never reopen public sign-up to make a');
40
+ p(' second account.');
41
+ p('- BETTER_AUTH_SECRET is required: .dev.vars locally, wrangler secret put for');
42
+ p(' the deployment. Without it sign-in is refused rather than validated.');
43
+ p('- Password reset sends through the CMS email seam, so it does nothing until');
44
+ p(' EMAIL_MODE, EMAIL_FROM, and the EMAIL binding are configured.');
45
+ return;
46
+ case 'access':
47
+ p('- Cloudflare Access signs people in; this worker only verifies what Access');
48
+ p(' forwards. Every admin request carries a signed assertion in');
49
+ p(' Cf-Access-Jwt-Assertion (or the CF_Authorization cookie behind it),');
50
+ p(' checked for signature, issuer, audience, and expiry before it is anybody.');
51
+ p('- There is NO user table here: no sign-up, no password, no password reset,');
52
+ p(' and no /v1/admin/users route. Who may sign in is the Access policy.');
53
+ p('- ACCESS_TEAM_DOMAIN, ACCESS_AUD, and the owner mapping are the whole');
54
+ p(' configuration, as vars in wrangler.jsonc. Owners are the addresses in');
55
+ p(' ACCESS_OWNER_EMAILS, or everyone when ACCESS_OWNER_DEFAULT is "true";');
56
+ p(' everyone else Access admits is a member. A REPLACE_WITH_ placeholder');
57
+ p(' reads as not configured, and npm run doctor names it.');
58
+ p('- wrangler dev has no Access in front of it, so /v1/admin is refused');
59
+ p(' locally. Do admin work through a deployed preview behind the Access');
60
+ p(' application.');
61
+ p('- NEVER fake or bypass an assertion: no hand-written Cf-Access-Jwt-Assertion');
62
+ p(' header, no test bypass in the provider, no swap to perimeter mode to get');
63
+ p(' past a local 401. The verification IS the auth.');
64
+ return;
65
+ case 'perimeter':
66
+ p('- PERIMETER MODE. This worker authenticates nobody: EVERY request that');
67
+ p(' reaches /v1/admin/* is the owner. That is content, settings, API keys,');
68
+ p(' and the form inbox, which is other people\'s personal data.');
69
+ p('- There is no user table, no sign-in screen, no sign-out, and no');
70
+ p(' /v1/admin/users route. Whatever sits in front of the deployment is the');
71
+ p(' only gate there is.');
72
+ p('- Never expose a route to this Worker that the perimeter does not cover,');
73
+ p(' the workers.dev subdomain included; disable that subdomain if it is');
74
+ p(' unused.');
75
+ p('- Never delete { acknowledged: true } from the registration to quiet the');
76
+ p(' doctor. It is how this project says it read the paragraph above, and');
77
+ p(' npm run doctor:remote fails a deployment without it.');
78
+ if (options.acknowledged === false) {
79
+ p('- The registration does NOT carry { acknowledged: true } today, so');
80
+ p(' npm run doctor:remote fails. Add it once perimeter mode is what this');
81
+ p(' site means, rather than deleting the check.');
82
+ }
83
+ return;
84
+ case 'external':
85
+ p('- The worker registers an admin auth provider of its own. Read src/index.ts');
86
+ p(' for which: a registration is a line of code and lives nowhere else.');
87
+ p('- The provider says WHO a request is; @we8/cms still decides WHAT that');
88
+ p(' identity may do, so the role split below is unchanged by it.');
89
+ p('- @we8/cms exports what a provider needs: adminAuth, requireOwner,');
90
+ p(' corsMiddleware, HttpError, errorBoundary, ok, parseOrThrow, and Bindings.');
91
+ p(' A provider claiming a path under /v1/admin/ mounts those gates itself.');
92
+ return;
93
+ case 'none':
94
+ p('- NO provider is registered, so every /v1/admin request is refused with 403');
95
+ p(' forbidden and the admin portal cannot be used. The public API is');
96
+ p(' unaffected and still serves.');
97
+ p('- That is the secure default, not a broken state. To open the admin,');
98
+ p(' register exactly one provider in src/index.ts:');
99
+ p(' npm install @we8/auth, then registerAdminAuth(embeddedAdminAuth)');
100
+ p(' or registerAdminAuth(cloudflareAccessAdminAuth()) from @we8/cloudflare');
101
+ p(' or registerAdminAuth(perimeterAdminAuth({ acknowledged: true })), which');
102
+ p(' makes EVERY request that reaches the worker the owner');
103
+ p('- Then npm run db:migrate (a provider brings its own tables) and');
104
+ p(' npx we8-cloudflare skill, to rewrite this file for the mode you chose.');
105
+ return;
106
+ default:
107
+ p('- The worker entry named by "main" in wrangler.jsonc could not be read, so');
108
+ p(' the mode is unverified. Read src/index.ts: the registerAdminAuth line is');
109
+ p(' the whole answer, and npm run doctor reports the same.');
110
+ p('- Rerun npx we8-cloudflare skill once that file is readable.');
111
+ }
112
+ }
113
+ /**
114
+ * The skill, as a string. One argument set in, one file out; no filesystem, no
115
+ * project name, nothing that would make two projects in the same mode disagree
116
+ * about how a we8 site is operated.
117
+ */
118
+ export function generateSkill(options) {
119
+ const lines = [];
120
+ const p = (line = '') => {
121
+ lines.push(line);
122
+ };
123
+ p('---');
124
+ p('name: we8');
125
+ p('description: Operate this we8 site. Use when working on the CMS, the admin');
126
+ p(' portal, content, forms, media, API keys, admin auth, AEO, wrangler, D1,');
127
+ p(' R2, local development, or a deploy in this project.');
128
+ p('---');
129
+ p();
130
+ p('# Operating this we8 project');
131
+ p();
132
+ p('This project IS a we8 CMS: one Cloudflare Worker, composed in src/index.ts');
133
+ p('from @we8/cms, configured by wrangler.jsonc, over its own D1 (bound DB) and');
134
+ p('R2 (bound MEDIA). The same worker serves the admin portal at / out of');
135
+ p('public/.');
136
+ if (options.site) {
137
+ p('The site/ workspace is an Astro frontend that reads this CMS over /v1.');
138
+ }
139
+ else {
140
+ p('The project is headless: any frontend reads this CMS over /v1.');
141
+ }
142
+ p();
143
+ p('The core is authless. registerAdminAuth(...) in src/index.ts is the WHOLE');
144
+ p('auth configuration: one line names the provider that says WHO a request is,');
145
+ p('and @we8/cms decides WHAT that identity may do. A worker registering no');
146
+ p('provider refuses every /v1/admin request with 403 forbidden and keeps');
147
+ p('serving the public API. That refusal is the secure default: fix the');
148
+ p('registration, never route around it.');
149
+ p();
150
+ p('## Commands');
151
+ p();
152
+ p('- npm run dev: the CMS and the bundled portal on http://localhost:8787');
153
+ p('- npm run db:migrate, db:migrate:remote: the schema. TWO directories apply');
154
+ p(' in order, the @we8/cms core migrations and then every installed');
155
+ p(' provider\'s (today node_modules/@we8/auth/migrations), and one command does');
156
+ p(' both. Running wrangler d1 migrations apply by hand applies only the first.');
157
+ p('- npm run db:seed: development data. LOCAL ONLY, it carries plaintext API');
158
+ p(' keys, and the command refuses every remote flag by design.');
159
+ p('- npm run doctor, doctor:remote: what is missing, plus the exact fix.');
160
+ p('- npm run admin:bundle: copies the built @we8/admin-app into public/, which');
161
+ p(' is how the worker serves the portal at /. Rerun it after upgrading the');
162
+ p(' portal package; an empty public/ means an API-only install.');
163
+ p('- npm run typecheck: compiles the registration against both packages, which');
164
+ p(' is what proves the auth seam still lines up.');
165
+ p('- npm run deploy: wrangler deploy to the Cloudflare account.');
166
+ if (options.site) {
167
+ p('- npm run site:dev, site:build: the Astro site. It builds from fixtures');
168
+ p(' until WE8_API_URL and WE8_PUBLISHABLE_KEY are set in site/.env.');
169
+ }
170
+ p('- npx we8-cloudflare skill: rewrite this file from the project\'s current');
171
+ p(' state. Run it after changing the auth registration; --check verifies it is');
172
+ p(' current and fails instead of writing, which is what belongs in CI.');
173
+ p();
174
+ p(`## ${MODE_HEADING[options.mode]}`);
175
+ p();
176
+ authSection(options, p);
177
+ p();
178
+ p('Whichever provider is registered:');
179
+ p();
180
+ p('- Roles are owner and member, and the split lives in @we8/cms: settings');
181
+ p(' mutation, the submissions inbox, API keys, and users are owner only.');
182
+ p('- No API key ever reaches /v1/admin/*. Presenting one there is refused');
183
+ p(' outright, because a publishable key travels in browser code by design.');
184
+ p('- GET /v1/auth/mode is keyless and reports the composed mode. That is the');
185
+ p(' way to learn the mode at runtime, and what the portal reads to decide');
186
+ p(' whether to show a sign-in screen at all.');
187
+ p();
188
+ p('## The API');
189
+ p();
190
+ p('- Everything public is under /v1 with one envelope, discriminated on ok.');
191
+ p(' Branch on the code field, never on the message.');
192
+ p('- Before writing API code, fetch GET /v1/openapi.json from the running');
193
+ p(' worker: it is this install\'s live contract and always matches the code.');
194
+ p('- Two key kinds: pk_ publishable in X-We8-Key, safe in browser code, and sk_');
195
+ p(' secret in Authorization: Bearer, for servers and build steps only. Both are');
196
+ p(' minted in the portal under Setup or at POST /v1/admin/keys; the secret is');
197
+ p(' shown exactly once, and a revoke takes effect on the next request.');
198
+ p('- Keyless routes: GET /v1/health, /v1/openapi.json, /v1/auth/mode,');
199
+ p(' /v1/sitemap.xml, GET /v1/media/*, and /llms.txt. Everything else public');
200
+ p(' needs a key.');
201
+ p('- Browser writes (form submissions, the visit and consent beacons) also need');
202
+ p(' the calling origin on settings.allowedOrigins, edited in the portal under');
203
+ p(' Setup, Integrations. A request with no Origin header passes.');
204
+ p('- A switched-off module answers 404, not 403.');
205
+ p();
206
+ p('## AEO');
207
+ p();
208
+ p('- Posts and site documents carry answerSummary (the answer, written to be');
209
+ p(' quoted verbatim) and questionHeading (the question it answers). Neither is');
210
+ p(' the excerpt, and an excerpt is not a substitute for either.');
211
+ p('- An authored answer becomes FAQPage JSON-LD on the post read and feeds');
212
+ p(' /llms.txt; render the jsonld object into a script tag exactly as it comes.');
213
+ p('- GET /v1/admin/aeo/checks lists the concrete gaps per post, and the portal');
214
+ p(' shows the same under Website. Fix findings in the post editor.');
215
+ p();
216
+ p('## Guardrails');
217
+ p();
218
+ p('- Never run the seed against a remote database and never weaken its');
219
+ p(' guardrails; never copy a seeded key into real content.');
220
+ p('- Never print, log, or commit an sk_ key, and never commit .dev.vars.');
221
+ p('- Set vars.SITE_URL to the real public origin before a production deploy:');
222
+ p(' the sitemap, llms.txt, and the JSON-LD are all built from it, and');
223
+ p(' doctor:remote fails a deployment still advertising localhost.');
224
+ p('- Form submissions are other people\'s personal data. Query them in place;');
225
+ p(' do not export, paste, or forward them.');
226
+ p('- When something fails, run npm run doctor before guessing.');
227
+ return `${lines.join('\n')}\n`;
228
+ }
229
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"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"}
@@ -10,18 +10,73 @@
10
10
  */
11
11
  /** The placeholder id a project carries until its D1 database exists. */
12
12
  export declare const D1_ID_PLACEHOLDER = "REPLACE_WITH_YOUR_D1_DATABASE_ID";
13
+ /**
14
+ * The placeholders an access-mode project carries until the Access application
15
+ * exists. They are written by the scaffolder, checked by the doctor, and read
16
+ * as "not configured" by the provider itself, so one convention covers all
17
+ * three rather than three near-misses.
18
+ */
19
+ export declare const ACCESS_TEAM_DOMAIN_PLACEHOLDER = "REPLACE_WITH_YOUR_ACCESS_TEAM_DOMAIN";
20
+ export declare const ACCESS_AUD_PLACEHOLDER = "REPLACE_WITH_YOUR_ACCESS_AUD_TAG";
21
+ export declare const ACCESS_OWNER_PLACEHOLDER = "REPLACE_WITH_YOUR_OWNER_EMAIL";
22
+ /** True for any value the scaffolder left for somebody to fill in. */
23
+ export declare function isPlaceholder(value: string): boolean;
24
+ /**
25
+ * The vars the Cloudflare Access provider reads.
26
+ *
27
+ * Named here, next to the generator that writes them, because three separate
28
+ * files depend on the spelling being identical: the provider that reads them at
29
+ * runtime, this generator that puts them in a project's config, and the doctor
30
+ * that checks they are filled in.
31
+ */
32
+ export declare const ACCESS_TEAM_DOMAIN_VAR = "ACCESS_TEAM_DOMAIN";
33
+ export declare const ACCESS_AUD_VAR = "ACCESS_AUD";
34
+ export declare const ACCESS_OWNER_EMAILS_VAR = "ACCESS_OWNER_EMAILS";
35
+ export declare const ACCESS_OWNER_DEFAULT_VAR = "ACCESS_OWNER_DEFAULT";
13
36
  /**
14
37
  * The compatibility date the CMS is written against. Pinned here rather than
15
38
  * set to today's date at scaffold time: a date the code has never run under is
16
39
  * a guess, and a guess in a compatibility date is a runtime surprise.
17
40
  */
18
41
  export declare const COMPATIBILITY_DATE = "2026-07-05";
19
- /** Where the migrations live in an installed project. */
42
+ /** Where the core migrations live in an installed project. */
20
43
  export declare const DEFAULT_MIGRATIONS_DIR = "node_modules/@we8/cms/migrations";
44
+ /**
45
+ * Where the embedded auth provider's migrations live, when it is installed.
46
+ *
47
+ * The schema of a we8 site comes from as many packages as it composes: the CMS
48
+ * owns its tables and `@we8/auth` owns the four Better Auth ones. Each ships
49
+ * its own numbered sequence with names that cannot collide, and
50
+ * `we8-cloudflare migrate` applies the core directory first and then this one.
51
+ */
52
+ export declare const AUTH_MIGRATIONS_DIR = "node_modules/@we8/auth/migrations";
53
+ /**
54
+ * The config `we8-cloudflare migrate` writes to apply a second migrations
55
+ * directory into the same database.
56
+ *
57
+ * `wrangler d1 migrations apply` reads exactly one `migrations_dir` from
58
+ * exactly one config, so applying two directories means running it twice with
59
+ * two configs. Everything that identifies the database is copied verbatim from
60
+ * the project's own config, because two runs against two different databases
61
+ * would be the bug this generates a file to avoid.
62
+ */
63
+ export declare function generateMigrationsConfig(source: {
64
+ name?: unknown;
65
+ compatibilityDate?: unknown;
66
+ databaseName?: unknown;
67
+ databaseId?: unknown;
68
+ }, migrationsDir: string): string;
21
69
  /** The daily retention sweep, matching the CMS package config. */
22
70
  export declare const RETENTION_CRON = "0 3 * * *";
23
71
  /** How a project sends mail. `off` is the default and drops every message. */
24
72
  export type EmailMode = 'off' | 'console' | 'cloudflare';
73
+ /**
74
+ * Which admin auth provider the project's worker entry composes. The generator
75
+ * only needs it for the configuration each mode implies: the session secret is
76
+ * an embedded-only obligation, the Access vars are an access-only one, and
77
+ * perimeter mode has no configuration at all, only a warning.
78
+ */
79
+ export type AdminAuthChoice = 'embedded' | 'access' | 'perimeter';
25
80
  /** Everything the generator needs. Everything else it decides. */
26
81
  export interface WranglerConfigAnswers {
27
82
  /** The Worker name, which is also its workers.dev subdomain. */
@@ -44,6 +99,14 @@ export interface WranglerConfigAnswers {
44
99
  emailMode?: EmailMode | undefined;
45
100
  /** The from-address, required when emailMode is `cloudflare`. */
46
101
  emailFrom?: string | undefined;
102
+ /** Defaults to `embedded`, which is what the scaffolder composes by default. */
103
+ adminAuth?: AdminAuthChoice | undefined;
104
+ /** The Access team domain, with `adminAuth: 'access'`. Placeholder when absent. */
105
+ accessTeamDomain?: string | undefined;
106
+ /** The Access application's AUD tag, with `adminAuth: 'access'`. */
107
+ accessAudience?: string | undefined;
108
+ /** The addresses that hold the owner role, with `adminAuth: 'access'`. */
109
+ accessOwnerEmails?: string | undefined;
47
110
  /** Defaults to node_modules/@we8/cms/migrations. */
48
111
  migrationsDir?: string | undefined;
49
112
  /** Defaults to the pinned COMPATIBILITY_DATE. */
@@ -1 +1 @@
1
- {"version":3,"file":"wrangler-config.d.ts","sourceRoot":"","sources":["../src/wrangler-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AAEzE,kEAAkE;AAClE,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzD,kEAAkE;AAClE,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AA2BD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CA6H7E"}
1
+ {"version":3,"file":"wrangler-config.d.ts","sourceRoot":"","sources":["../src/wrangler-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,yCAAyC,CAAC;AACrF,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AACzE,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAExE,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C,8DAA8D;AAC9D,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,sCAAsC,CAAC;AAEvE;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE;IACN,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,EACD,aAAa,EAAE,MAAM,GACpB,MAAM,CAkBR;AAED,kEAAkE;AAClE,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE,kEAAkE;AAClE,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,gFAAgF;IAChF,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACxC,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AA2BD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAsL7E"}