@cogenta/cli 0.2.2 → 0.4.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 (71) hide show
  1. package/dist/admin-assets/assets/index-C9a7O_Xs.css +1 -0
  2. package/dist/admin-assets/assets/index-DXvMgWvn.js +74 -0
  3. package/dist/admin-assets/fonts/ibm-plex-mono-400.woff2 +0 -0
  4. package/dist/admin-assets/fonts/ibm-plex-mono-500.woff2 +0 -0
  5. package/dist/admin-assets/fonts/ibm-plex-mono-600.woff2 +0 -0
  6. package/dist/admin-assets/fonts/ibm-plex-mono-700.woff2 +0 -0
  7. package/dist/admin-assets/fonts/ibm-plex-sans-var.woff2 +0 -0
  8. package/dist/admin-assets/index.html +2 -2
  9. package/dist/commands/assistant.d.ts +65 -0
  10. package/dist/commands/assistant.d.ts.map +1 -0
  11. package/dist/commands/assistant.js +207 -0
  12. package/dist/commands/assistant.js.map +1 -0
  13. package/dist/commands/content-webhooks.d.ts +41 -0
  14. package/dist/commands/content-webhooks.d.ts.map +1 -0
  15. package/dist/commands/content-webhooks.js +61 -0
  16. package/dist/commands/content-webhooks.js.map +1 -0
  17. package/dist/commands/http-security.d.ts +39 -0
  18. package/dist/commands/http-security.d.ts.map +1 -0
  19. package/dist/commands/http-security.js +153 -0
  20. package/dist/commands/http-security.js.map +1 -0
  21. package/dist/commands/links.d.ts +24 -0
  22. package/dist/commands/links.d.ts.map +1 -0
  23. package/dist/commands/links.js +109 -0
  24. package/dist/commands/links.js.map +1 -0
  25. package/dist/commands/media-images.d.ts +67 -0
  26. package/dist/commands/media-images.d.ts.map +1 -0
  27. package/dist/commands/media-images.js +107 -0
  28. package/dist/commands/media-images.js.map +1 -0
  29. package/dist/commands/search-page.d.ts +40 -0
  30. package/dist/commands/search-page.d.ts.map +1 -0
  31. package/dist/commands/search-page.js +104 -0
  32. package/dist/commands/search-page.js.map +1 -0
  33. package/dist/commands/security-alerts.d.ts +24 -0
  34. package/dist/commands/security-alerts.d.ts.map +1 -0
  35. package/dist/commands/security-alerts.js +82 -0
  36. package/dist/commands/security-alerts.js.map +1 -0
  37. package/dist/commands/seo.d.ts +88 -0
  38. package/dist/commands/seo.d.ts.map +1 -0
  39. package/dist/commands/seo.js +155 -0
  40. package/dist/commands/seo.js.map +1 -0
  41. package/dist/commands/serve.d.ts +138 -4
  42. package/dist/commands/serve.d.ts.map +1 -1
  43. package/dist/commands/serve.js +1145 -43
  44. package/dist/commands/serve.js.map +1 -1
  45. package/dist/commands/site-plan.d.ts +86 -0
  46. package/dist/commands/site-plan.d.ts.map +1 -0
  47. package/dist/commands/site-plan.js +235 -0
  48. package/dist/commands/site-plan.js.map +1 -0
  49. package/dist/commands/theme-css.d.ts +54 -0
  50. package/dist/commands/theme-css.d.ts.map +1 -0
  51. package/dist/commands/theme-css.js +121 -0
  52. package/dist/commands/theme-css.js.map +1 -0
  53. package/dist/commands/theme-render.d.ts +115 -4
  54. package/dist/commands/theme-render.d.ts.map +1 -1
  55. package/dist/commands/theme-render.js +260 -17
  56. package/dist/commands/theme-render.js.map +1 -1
  57. package/dist/commands/users.d.ts +7 -1
  58. package/dist/commands/users.d.ts.map +1 -1
  59. package/dist/commands/users.js +129 -15
  60. package/dist/commands/users.js.map +1 -1
  61. package/dist/index.d.ts +2 -0
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +31 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/reset-mail.d.ts +39 -0
  66. package/dist/reset-mail.d.ts.map +1 -0
  67. package/dist/reset-mail.js +45 -0
  68. package/dist/reset-mail.js.map +1 -0
  69. package/package.json +15 -10
  70. package/dist/admin-assets/assets/index-21ZcDkDC.css +0 -1
  71. package/dist/admin-assets/assets/index-BXVsXHD2.js +0 -23
@@ -0,0 +1,88 @@
1
+ import { type AccessContext, type ContentGateway } from '@cogenta/api';
2
+ import type { CollectionDefinition, ContentEntry } from '@cogenta/schema';
3
+ import { type HreflangAlternate, type SeoImage, type SeoResource, type SeoSite, type SitemapFile } from '@cogenta/seo';
4
+ /**
5
+ * `@cogenta/seo`, actually wired to the server (L10, tasks 1-2).
6
+ *
7
+ * The package was written and tested against values, never against a running
8
+ * `cogenta serve` — the lot names that gap explicitly. This module is the one
9
+ * place the two meet: it converts what `serve.ts` holds (a `ContentGateway`,
10
+ * a `CollectionDefinition`, a `ContentEntry`) into what `@cogenta/seo` takes
11
+ * (`SeoSite`, `SeoResource`) and nothing else. No SEO decision is re-made
12
+ * here — every tag, every URL and every published/not-published judgement is
13
+ * still the package's own.
14
+ */
15
+ export interface SiteIdentity {
16
+ readonly name: string;
17
+ readonly url: string;
18
+ readonly locales: readonly string[];
19
+ readonly defaultLocale: string;
20
+ }
21
+ /**
22
+ * The site as the SEO layer sees it.
23
+ *
24
+ * `unprefixedDefaultLocale` is `true` because that is what this server
25
+ * actually does: `createRequestListener` hands `matchPath` a `defaultLocale`,
26
+ * and `matchPath` then resolves `/blog/hello` as well as `/en/blog/hello`.
27
+ * Saying otherwise would emit canonicals that redirect to themselves — the
28
+ * exact failure `SeoSite`'s own doc comment warns about.
29
+ */
30
+ export declare function seoSiteFor(site: SiteIdentity): SeoSite;
31
+ /**
32
+ * Every published entry of every routed collection, as SEO resources.
33
+ *
34
+ * Read as `ANONYMOUS` on purpose, whoever asked for the sitemap: a sitemap is
35
+ * a public document, and building it from the requesting actor's permissions
36
+ * would give a signed-in editor a different — larger — sitemap than the one a
37
+ * crawler fetches. `indexableResources` filters the unpublished half again on
38
+ * its way out, so the guarantee is doubled rather than trusted once.
39
+ */
40
+ export declare function collectRoutedResources(collections: readonly CollectionDefinition[], gateway: ContentGateway): Promise<readonly SeoResource[]>;
41
+ /**
42
+ * The `hreflang` alternates for one entry, or an empty list.
43
+ *
44
+ * Skipped outright on a single-locale site: `alternatesFor` would return
45
+ * nothing anyway, and the family lookup is a filtered scan of the collection —
46
+ * work every page render on a monolingual site would pay for a guaranteed
47
+ * empty answer.
48
+ *
49
+ * The family is read through the same permission-checked gateway as the page
50
+ * itself, with the same actor, so a translation the caller may not see never
51
+ * becomes an alternate.
52
+ */
53
+ export declare function alternatesForEntry(site: SeoSite, collection: CollectionDefinition, entry: ContentEntry, gateway: ContentGateway, context: AccessContext, locales: readonly string[]): Promise<readonly HreflangAlternate[]>;
54
+ export interface HeadOptions {
55
+ readonly alternates?: readonly HreflangAlternate[];
56
+ /** Resolves a media id to something a crawler can use. Absent means no social image. */
57
+ readonly media?: (id: string) => SeoImage | null;
58
+ /** Forces `noindex` — a search results page, a preview. */
59
+ readonly noindex?: boolean;
60
+ /** Overrides the derived title. Used for pages that are not one entry. */
61
+ readonly title?: string;
62
+ }
63
+ /**
64
+ * The whole `<head>` an entry earns: title, description, canonical,
65
+ * `hreflang`, Open Graph, Twitter Card and a JSON-LD block.
66
+ *
67
+ * Returned as one HTML string because that is what the page template needs;
68
+ * every escaping decision inside it belongs to `@cogenta/seo` (`renderMetaTags`
69
+ * for attributes, `renderJsonLdScript` for the `</script>` hazard), never to
70
+ * this file.
71
+ */
72
+ export declare function renderSeoHead(site: SeoSite, resource: SeoResource, options?: HeadOptions): string;
73
+ /**
74
+ * The sitemap files a site needs — one below the protocol limits, an index
75
+ * plus chunks above them.
76
+ *
77
+ * Returned as the whole set rather than one document because the split is not
78
+ * this layer's decision to hide: `serve.ts` routes `/sitemap.xml` *and*
79
+ * `/sitemap-N.xml` from the same array, so a site that grows past 50 000 URLs
80
+ * starts serving an index without anybody changing a route.
81
+ */
82
+ export declare function buildSitemapFiles(site: SeoSite, resources: readonly SeoResource[]): readonly SitemapFile[];
83
+ export interface RobotsRenderOptions {
84
+ /** False on a staging or preview host: blocks every crawler outright. */
85
+ readonly allowIndexing?: boolean;
86
+ }
87
+ export declare function renderRobots(site: SeoSite, options?: RobotsRenderOptions): string;
88
+ //# sourceMappingURL=seo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/commands/seo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAEjF,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACzE,OAAO,EAML,KAAK,iBAAiB,EAItB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,WAAW,EAEjB,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAQtD;AAQD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAC5C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAuCjC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CA0BvC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAClD,wFAAwF;IACxF,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,IAAI,CAAA;IAChD,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,WAAgB,GACxB,MAAM,CAkBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,SAAS,WAAW,EAAE,GAChC,SAAS,WAAW,EAAE,CAExB;AAED,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CACjC;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAUrF"}
@@ -0,0 +1,155 @@
1
+ import { ANONYMOUS } from '@cogenta/api';
2
+ import { isCogentaError } from '@cogenta/core';
3
+ import { alternatesFor, buildJsonLd, buildMetaTags, buildSitemap, groupTranslationFamilies, renderJsonLdScript, renderMetaTags, renderRobotsTxt, sitemapUrlsFor, } from '@cogenta/seo';
4
+ /**
5
+ * The site as the SEO layer sees it.
6
+ *
7
+ * `unprefixedDefaultLocale` is `true` because that is what this server
8
+ * actually does: `createRequestListener` hands `matchPath` a `defaultLocale`,
9
+ * and `matchPath` then resolves `/blog/hello` as well as `/en/blog/hello`.
10
+ * Saying otherwise would emit canonicals that redirect to themselves — the
11
+ * exact failure `SeoSite`'s own doc comment warns about.
12
+ */
13
+ export function seoSiteFor(site) {
14
+ return {
15
+ baseUrl: site.url,
16
+ name: site.name,
17
+ defaultLocale: site.defaultLocale,
18
+ locales: site.locales,
19
+ unprefixedDefaultLocale: true,
20
+ };
21
+ }
22
+ /** How many entries one collection contributes to a sitemap before it is cut off. */
23
+ const MAX_SITEMAP_ENTRIES_PER_COLLECTION = 5_000;
24
+ /** Page size used to walk a collection. The gateway's own ceiling is 100. */
25
+ const SCAN_PAGE = 100;
26
+ /**
27
+ * Every published entry of every routed collection, as SEO resources.
28
+ *
29
+ * Read as `ANONYMOUS` on purpose, whoever asked for the sitemap: a sitemap is
30
+ * a public document, and building it from the requesting actor's permissions
31
+ * would give a signed-in editor a different — larger — sitemap than the one a
32
+ * crawler fetches. `indexableResources` filters the unpublished half again on
33
+ * its way out, so the guarantee is doubled rather than trusted once.
34
+ */
35
+ export async function collectRoutedResources(collections, gateway) {
36
+ const context = { actor: ANONYMOUS };
37
+ const resources = [];
38
+ for (const collection of collections) {
39
+ if (collection.routing === undefined)
40
+ continue;
41
+ // A routed collection the `public` role may not read at all makes the
42
+ // gateway *throw* `FORBIDDEN` rather than answer an empty page. Skipping
43
+ // it is the right answer — such a collection has no public URLs to list —
44
+ // and catching is what keeps one login-only section from turning
45
+ // `/sitemap.xml` into a 500 for every crawler. Found by the security
46
+ // review of L10 task 2.
47
+ try {
48
+ let cursor;
49
+ let read = 0;
50
+ for (;;) {
51
+ const page = await gateway.list({
52
+ collection: collection.name,
53
+ limit: SCAN_PAGE,
54
+ ...(cursor === undefined ? {} : { after: cursor }),
55
+ }, context);
56
+ for (const entry of page.items)
57
+ resources.push({ collection, entry });
58
+ read += page.items.length;
59
+ const next = page.nextCursor;
60
+ if (next === null || read >= MAX_SITEMAP_ENTRIES_PER_COLLECTION)
61
+ break;
62
+ cursor = next;
63
+ }
64
+ }
65
+ catch (error) {
66
+ if (isCogentaError(error) && error.code === 'FORBIDDEN')
67
+ continue;
68
+ throw error;
69
+ }
70
+ }
71
+ return resources;
72
+ }
73
+ /**
74
+ * The `hreflang` alternates for one entry, or an empty list.
75
+ *
76
+ * Skipped outright on a single-locale site: `alternatesFor` would return
77
+ * nothing anyway, and the family lookup is a filtered scan of the collection —
78
+ * work every page render on a monolingual site would pay for a guaranteed
79
+ * empty answer.
80
+ *
81
+ * The family is read through the same permission-checked gateway as the page
82
+ * itself, with the same actor, so a translation the caller may not see never
83
+ * becomes an alternate.
84
+ */
85
+ export async function alternatesForEntry(site, collection, entry, gateway, context, locales) {
86
+ if (locales.length < 2)
87
+ return [];
88
+ const sourceId = entry.translationOf ?? entry.id;
89
+ const page = await gateway.list({
90
+ collection: collection.name,
91
+ filter: {
92
+ or: [
93
+ { field: 'id', operator: 'eq', value: sourceId },
94
+ { field: 'translationOf', operator: 'eq', value: sourceId },
95
+ ],
96
+ },
97
+ limit: SCAN_PAGE,
98
+ }, context);
99
+ const resources = page.items.map((found) => ({ collection, entry: found }));
100
+ const family = groupTranslationFamilies(site, resources).find((candidate) => candidate.sourceId === sourceId);
101
+ // A family of one is not a family: a self-referencing `hreflang` is noise,
102
+ // and `buildHreflangMap` drops it for the same reason.
103
+ if (family === undefined || family.members.length < 2)
104
+ return [];
105
+ return alternatesFor(site, family);
106
+ }
107
+ /**
108
+ * The whole `<head>` an entry earns: title, description, canonical,
109
+ * `hreflang`, Open Graph, Twitter Card and a JSON-LD block.
110
+ *
111
+ * Returned as one HTML string because that is what the page template needs;
112
+ * every escaping decision inside it belongs to `@cogenta/seo` (`renderMetaTags`
113
+ * for attributes, `renderJsonLdScript` for the `</script>` hazard), never to
114
+ * this file.
115
+ */
116
+ export function renderSeoHead(site, resource, options = {}) {
117
+ const tags = buildMetaTags(site, resource, {
118
+ ...(options.alternates === undefined ? {} : { alternates: options.alternates }),
119
+ ...(options.media === undefined ? {} : { resolvers: { media: options.media } }),
120
+ ...(options.noindex === undefined ? {} : { noindex: options.noindex }),
121
+ ...(options.title === undefined ? {} : { title: options.title }),
122
+ });
123
+ const parts = [renderMetaTags(tags)];
124
+ const graph = buildJsonLd(site, resource, {
125
+ ...(options.media === undefined ? {} : { resolvers: { media: options.media } }),
126
+ });
127
+ if (graph !== null && options.noindex !== true) {
128
+ parts.push(`<script type="application/ld+json">${renderJsonLdScript(graph)}</script>`);
129
+ }
130
+ return parts.join('\n');
131
+ }
132
+ /**
133
+ * The sitemap files a site needs — one below the protocol limits, an index
134
+ * plus chunks above them.
135
+ *
136
+ * Returned as the whole set rather than one document because the split is not
137
+ * this layer's decision to hide: `serve.ts` routes `/sitemap.xml` *and*
138
+ * `/sitemap-N.xml` from the same array, so a site that grows past 50 000 URLs
139
+ * starts serving an index without anybody changing a route.
140
+ */
141
+ export function buildSitemapFiles(site, resources) {
142
+ return buildSitemap(site, sitemapUrlsFor(site, resources));
143
+ }
144
+ export function renderRobots(site, options = {}) {
145
+ return renderRobotsTxt({
146
+ site,
147
+ sitemaps: ['/sitemap.xml'],
148
+ // The admin is a signed-in application, not content. Nothing there is
149
+ // reachable without a session anyway, but a crawler has no reason to
150
+ // spend requests discovering that.
151
+ groups: [{ userAgent: '*', allow: ['/'], disallow: ['/admin', '/api/'] }],
152
+ ...(options.allowIndexing === undefined ? {} : { allowIndexing: options.allowIndexing }),
153
+ });
154
+ }
155
+ //# sourceMappingURL=seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.js","sourceRoot":"","sources":["../../src/commands/seo.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,14 @@
1
1
  import { type IncomingMessage, type ServerResponse } from 'node:http';
2
- import { type AgentsRouter, type AuditRouter, type AuthRouter, createContentGateway, type MediaRouter, type RestRouter } from '@cogenta/api';
2
+ import { type AnalyticsStore } from '@cogenta/analytics';
3
+ import { type AgentsRouter, type AnalyticsRouter, type ApiKeysRouter, type AssistantRouter, type AuditRouter, type AuthRouter, createContentGateway, type ImportRouter, type MarketplaceRouter, type MediaImageProcessor, type MediaRouter, type MenuRouter, type NoticeRouter, type OpsStatusRouter, type PermissionLayer, type RedirectRouter, type RestRouter, type SearchRouter, type SitePlanRouter, type TaxonomyRouter, type UsersRouter } from '@cogenta/api';
3
4
  import { type AuthStore } from '@cogenta/auth';
5
+ import { type CommerceAdminRouter } from '@cogenta/commerce';
4
6
  import { type DatabaseHandle, type HealthReport, type Logger, type MediaStore, type StorageDriver } from '@cogenta/core';
5
- import { type CollectionDefinition, type SchemaDocument } from '@cogenta/schema';
7
+ import { type CollectionDefinition, type RedirectStore, type SchemaDocument, type TaxonomyDefinition } from '@cogenta/schema';
6
8
  import type { GraphQLSchema } from 'graphql';
7
9
  import type { Output, Writer } from '../output.js';
10
+ import { type SecurityConfig } from './http-security.js';
11
+ import { type SecurityAlertWatch } from './security-alerts.js';
8
12
  /**
9
13
  * Loads a project's content model.
10
14
  *
@@ -15,6 +19,30 @@ import type { Output, Writer } from '../output.js';
15
19
  * collections has nothing to serve.
16
20
  */
17
21
  export declare function loadCollections(projectRoot: string): Promise<readonly CollectionDefinition[]>;
22
+ /** What a project's schema file declares: collections, and since `schema@2.0` taxonomies. */
23
+ export interface LoadedSchema {
24
+ readonly collections: readonly CollectionDefinition[];
25
+ readonly taxonomies: readonly TaxonomyDefinition[];
26
+ }
27
+ /**
28
+ * The same file, read for both halves of the content model.
29
+ *
30
+ * Taxonomies arrive as a **named** export beside the default one
31
+ * (`export const taxonomies = [...]`), so every schema file written before
32
+ * `schema@2.0` keeps loading unchanged and simply declares none.
33
+ */
34
+ export declare function loadSchemaModule(projectRoot: string): Promise<LoadedSchema>;
35
+ /**
36
+ * The schema file this project actually loads, or `undefined` when it has
37
+ * none.
38
+ *
39
+ * Anything that *writes* the schema back has to target this, not a guessed
40
+ * name: `loadCollections` prefers `cogenta.schema.ts` (the form ADR-0010
41
+ * calls for — TypeScript in git), so a writer that assumed `.mjs` would
42
+ * create tables and then write a file nothing reads, leaving an operator
43
+ * with orphan tables and no collections after the restart it was told to do.
44
+ */
45
+ export declare function findSchemaFile(projectRoot: string): Promise<string | undefined>;
18
46
  interface Site {
19
47
  readonly db: DatabaseHandle;
20
48
  readonly auth: AuthStore;
@@ -22,29 +50,116 @@ interface Site {
22
50
  readonly authRouter: AuthRouter;
23
51
  readonly mediaRouter: MediaRouter;
24
52
  readonly auditRouter: AuditRouter;
53
+ /** `GET /api/search` — the full-text index, reachable for the first time (L10 task 3). */
54
+ readonly searchRouter: SearchRouter;
55
+ /**
56
+ * Self-hosted, cookie-free page-view analytics (`@cogenta/analytics`).
57
+ *
58
+ * `analyticsStore` is the aggregate/write side used both by `analyticsRouter`
59
+ * (`/api/analytics/beacon` and `/api/analytics/summary`) and directly by the
60
+ * admin dashboard widget's server-rendered data. Always mounted — a site
61
+ * with nobody reading the dashboard still collects nothing more than it
62
+ * would with the feature switched off (R1/R2 spirit: purely additive).
63
+ */
64
+ readonly analyticsStore: AnalyticsStore;
65
+ readonly analyticsRouter: AnalyticsRouter;
66
+ /** `/api/taxonomies/*` — terms, mounted apart from content because a taxonomy is not a collection (`schema@2.0`, ADR-0022). */
67
+ readonly taxonomyRouter: TaxonomyRouter;
68
+ /** `/api/marketplace/*` — L17's local plugin/theme/skin catalog, reusing `@cogenta/plugins`' real Ed25519 verification unchanged. Always mounted; the catalog is empty until a site configures one. */
69
+ readonly marketplaceRouter: MarketplaceRouter;
70
+ /** `/api/menus/*` — navigation menus. Not schema-declared like a taxonomy: created and edited entirely at runtime, so this is always mounted, empty until the admin (or the API) creates the first one. */
71
+ readonly menuRouter: MenuRouter;
72
+ /**
73
+ * `/api/commerce/*` — contract E's back office (ADR-0024), mounted for the
74
+ * first time. `@cogenta/commerce`'s tables are only created and this
75
+ * router is only present once a site actually reaches this point — a site
76
+ * that never sells anything never pays for it (mirrors the taxonomy story).
77
+ */
78
+ readonly commerceRouter: CommerceAdminRouter;
79
+ /** `/api/redirects` — admin-only management of the redirect table `cogenta serve` already applies to every public GET (audit follow-up to L10 task 2). */
80
+ readonly redirectRouter: RedirectRouter;
81
+ /** `GET /api/security-status` and `GET /api/webhooks-status` — read-only mirrors of the site's configuration file, admin-only (audit follow-up to L10 task 6 / L14 task 1). */
82
+ readonly opsStatusRouter: OpsStatusRouter;
83
+ /** ADR-0021's half that replaces the MFA sign-in gate: recommendations the admin shows, never a block. */
84
+ readonly noticeRouter: NoticeRouter;
85
+ /** Refused sign-ins, watched for a run worth alerting on (L14 task 4). `null` when nothing is configured to receive one. */
86
+ readonly securityAlerts: SecurityAlertWatch | null;
87
+ /** Account management from the admin instead of `cogenta users create` on a terminal (L11 task 3). */
88
+ readonly usersRouter: UsersRouter;
89
+ /** `/api/api-keys` — machine-to-machine bearer credentials, admin-only (L13 task 8). */
90
+ readonly apiKeysRouter: ApiKeysRouter;
25
91
  /** Only set when a caller passes `agents` into `assembleSite` — no site constructs one today (R2: agents are optional, not a hard dependency of the CMS). */
26
92
  readonly agentsRouter?: AgentsRouter;
93
+ /**
94
+ * `/api/site-plans` — L19 task 7's document-driven planning on a live site.
95
+ *
96
+ * Always mounted, even with no LLM provider: the drafts an installer left
97
+ * behind must still be readable, and the router itself answers
98
+ * `SITE_PLAN_NO_PROVIDER` for the routes that would need a model.
99
+ */
100
+ readonly sitePlanRouter?: SitePlanRouter;
101
+ /**
102
+ * `/api/import` — the admin's counterpart to `cogenta import wordpress` on
103
+ * a terminal. Always mounted: unlike the site planner it needs no external
104
+ * provider, only this site's own database and storage, which `assembleSite`
105
+ * already has in scope.
106
+ */
107
+ readonly importRouter: ImportRouter;
108
+ /**
109
+ * `/api/assistant` — L18. Always mounted, even on a site with no AI provider:
110
+ * it is the route that *answers* `{available: false}`, which is what lets the
111
+ * admin panel disappear instead of erroring.
112
+ */
113
+ readonly assistantRouter: AssistantRouter;
27
114
  /** Not routed through `mediaRouter`: serving a binary body is outside the JSON-only `RestResponse` shape, so the file route is handled directly (same treatment `/api/schema` already gets). */
28
115
  readonly mediaStore: MediaStore;
29
116
  readonly storage: StorageDriver;
117
+ /** `null` when no image driver loaded — `/_image` then serves originals only. */
118
+ readonly images: MediaImageProcessor | null;
30
119
  readonly graphqlSchema: GraphQLSchema;
31
120
  readonly gateway: ReturnType<typeof createContentGateway>;
121
+ /**
122
+ * The same layer the gateway and the REST service already ask. Held here so
123
+ * the routes this file serves itself — the page builder's draft render — can
124
+ * ask the one authority too, rather than re-deciding who may edit (R4).
125
+ */
126
+ readonly permissions: PermissionLayer;
32
127
  /** `.cogenta/schema.json`'s in-memory twin — the admin's only view of the collections (never the schema modules themselves, which are Node code). */
33
128
  readonly schemaDocument: SchemaDocument;
129
+ /**
130
+ * The redirect table, applied to *every* GET before routing (L10 task 2).
131
+ *
132
+ * It was already reachable through `/api/content/-/by-path`, which only the
133
+ * API's own clients call — a browser asking for a renamed URL never went
134
+ * near it and got a 404 instead of the 301 the rename created.
135
+ */
136
+ readonly redirects: RedirectStore;
34
137
  readonly collections: readonly CollectionDefinition[];
138
+ readonly taxonomies: readonly TaxonomyDefinition[];
35
139
  readonly site: {
36
140
  readonly name: string;
37
141
  readonly url: string;
38
142
  readonly locales: readonly string[];
39
143
  readonly defaultLocale: string;
144
+ /** Which page answers an unmatched URL (L14 task 2). `/404` by default. */
145
+ readonly notFoundPath: string;
40
146
  };
41
- /** `null` when the project has no `theme.tokens.json` — the theme-render fallback serves unstyled HTML rather than refusing. */
42
- readonly skinCss: string | null;
147
+ /** The skin's custom properties plus the theme's own stylesheet, minified into one. `null` when neither could be loaded — the theme-render fallback serves unstyled HTML rather than refusing. */
148
+ readonly styles: string | null;
149
+ /** CORS, security headers and cache-control, applied to every response (L10 task 6). */
150
+ readonly security: SecurityConfig;
43
151
  /** Live, not cached: a driver that just went down must show as down the next time this is called, not until the process restarts. */
44
152
  readonly health: () => Promise<{
45
153
  readonly database: HealthReport;
46
154
  readonly storage: HealthReport;
47
155
  }>;
156
+ /**
157
+ * Drains one batch of due scheduled-publication jobs. `runServe` calls this
158
+ * on a `setInterval` for as long as the process runs — see its comment for
159
+ * why a fixed period is the honest, R1-compliant substitute for a real
160
+ * worker. Exposed so a test can call it directly instead of waiting.
161
+ */
162
+ readonly tickScheduledPublishing: () => Promise<number>;
48
163
  dispose(): Promise<void>;
49
164
  }
50
165
  /**
@@ -79,6 +194,25 @@ export interface ServeOptions {
79
194
  * decision for whoever deploys a read-only instance, not made here.
80
195
  */
81
196
  readonly readOnly?: boolean;
197
+ /**
198
+ * `cogenta dev` sets this; `cogenta serve` does not.
199
+ *
200
+ * It gates exactly one thing today: whether an approved site plan may be
201
+ * **applied** (L19 task 7). ADR-0010 is explicit — "l'éditeur visuel de
202
+ * schéma écrit ces fichiers, mais uniquement en mode développement. En
203
+ * production le schéma est en lecture seule" — and applying a plan writes
204
+ * `cogenta.schema.*` and creates tables, which is exactly that editor by
205
+ * another name. Proposing and reviewing a plan stay available everywhere;
206
+ * only the write is held to the decision.
207
+ */
208
+ readonly development?: boolean;
209
+ /**
210
+ * Overrides `SCHEDULED_PUBLISH_TICK_MS`. Not a CLI flag — an operator has
211
+ * no reason to change a 60-second cadence, and this exists so a test can
212
+ * prove the interval really drains the queue without waiting a minute for
213
+ * it.
214
+ */
215
+ readonly scheduledPublishTickMs?: number;
82
216
  }
83
217
  /**
84
218
  * Runs until `options.signal` aborts. Returns 0 on a clean shutdown, 1 if
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}