@cogenta/core 0.3.0 → 0.6.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.
- package/CHANGELOG.md +3479 -0
- package/dist/config/env.d.ts +21 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +72 -0
- package/dist/config/env.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/load-config.d.ts +9 -0
- package/dist/config/load-config.d.ts.map +1 -1
- package/dist/config/load-config.js +39 -15
- package/dist/config/load-config.js.map +1 -1
- package/dist/config/resolve-config.d.ts.map +1 -1
- package/dist/config/resolve-config.js +47 -0
- package/dist/config/resolve-config.js.map +1 -1
- package/dist/config/schema.d.ts +55 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +164 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/secret-hygiene.d.ts +55 -0
- package/dist/config/secret-hygiene.d.ts.map +1 -0
- package/dist/config/secret-hygiene.js +94 -0
- package/dist/config/secret-hygiene.js.map +1 -0
- package/dist/config/types.d.ts +192 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +4 -0
- package/dist/config/types.js.map +1 -1
- package/dist/drivers/index.d.ts +1 -1
- package/dist/drivers/index.d.ts.map +1 -1
- package/dist/drivers/index.js.map +1 -1
- package/dist/drivers/registry.d.ts.map +1 -1
- package/dist/drivers/registry.js +15 -8
- package/dist/drivers/registry.js.map +1 -1
- package/dist/drivers/types.d.ts +23 -0
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/errors/codes.d.ts +1 -1
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +259 -0
- package/dist/errors/codes.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/logger/error-log.d.ts +48 -0
- package/dist/logger/error-log.d.ts.map +1 -0
- package/dist/logger/error-log.js +57 -0
- package/dist/logger/error-log.js.map +1 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +1 -0
- package/dist/logger/index.js.map +1 -1
- package/dist/media/exif.d.ts +46 -0
- package/dist/media/exif.d.ts.map +1 -0
- package/dist/media/exif.js +291 -0
- package/dist/media/exif.js.map +1 -0
- package/dist/media/folder-path.d.ts +16 -0
- package/dist/media/folder-path.d.ts.map +1 -0
- package/dist/media/folder-path.js +51 -0
- package/dist/media/folder-path.js.map +1 -0
- package/dist/media/folder-store.d.ts +26 -0
- package/dist/media/folder-store.d.ts.map +1 -0
- package/dist/media/folder-store.js +361 -0
- package/dist/media/folder-store.js.map +1 -0
- package/dist/media/index.d.ts +5 -2
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +4 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/sql-fragments.d.ts +19 -0
- package/dist/media/sql-fragments.d.ts.map +1 -0
- package/dist/media/sql-fragments.js +29 -0
- package/dist/media/sql-fragments.js.map +1 -0
- package/dist/media/store.d.ts +1 -0
- package/dist/media/store.d.ts.map +1 -1
- package/dist/media/store.js +175 -20
- package/dist/media/store.js.map +1 -1
- package/dist/media/types.d.ts +148 -0
- package/dist/media/types.d.ts.map +1 -1
- package/dist/queue/bullmq.d.ts +4 -0
- package/dist/queue/bullmq.d.ts.map +1 -1
- package/dist/queue/bullmq.js +53 -10
- package/dist/queue/bullmq.js.map +1 -1
- package/dist/queue/database.d.ts.map +1 -1
- package/dist/queue/database.js +32 -11
- package/dist/queue/database.js.map +1 -1
- package/dist/queue/types.d.ts +19 -0
- package/dist/queue/types.d.ts.map +1 -1
- package/dist/rate-limit/index.d.ts +21 -0
- package/dist/rate-limit/index.d.ts.map +1 -0
- package/dist/rate-limit/index.js +25 -0
- package/dist/rate-limit/index.js.map +1 -0
- package/dist/rate-limit/memory.d.ts +17 -0
- package/dist/rate-limit/memory.d.ts.map +1 -0
- package/dist/rate-limit/memory.js +61 -0
- package/dist/rate-limit/memory.js.map +1 -0
- package/dist/rate-limit/redis.d.ts +55 -0
- package/dist/rate-limit/redis.d.ts.map +1 -0
- package/dist/rate-limit/redis.js +134 -0
- package/dist/rate-limit/redis.js.map +1 -0
- package/dist/rate-limit/types.d.ts +52 -0
- package/dist/rate-limit/types.d.ts.map +1 -0
- package/dist/rate-limit/types.js +2 -0
- package/dist/rate-limit/types.js.map +1 -0
- package/dist/version.d.ts +39 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +84 -0
- package/dist/version.js.map +1 -0
- package/package.json +3 -2
package/dist/config/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { CACHE_DRIVERS, DATABASE_DRIVERS, EMBEDDINGS_PROVIDERS, IMAGE_GENERATION_PROVIDERS, QUEUE_DRIVERS, STORAGE_DRIVERS, VECTOR_DRIVERS, } from './types.js';
|
|
2
|
+
import { CACHE_DRIVERS, DATABASE_DRIVERS, EMBEDDINGS_PROVIDERS, IMAGE_GENERATION_PROVIDERS, PAYMENT_DRIVERS, QUEUE_DRIVERS, RATE_LIMIT_DRIVERS, STORAGE_DRIVERS, VECTOR_DRIVERS, } from './types.js';
|
|
3
3
|
const nonEmpty = z.string().min(1);
|
|
4
4
|
// Every object is strict: a typo in a key is an error, never a silently ignored
|
|
5
5
|
// setting. Config drift between staging and production is the daily pain this
|
|
@@ -45,6 +45,10 @@ const queueSchema = z.strictObject({
|
|
|
45
45
|
driver: z.enum(QUEUE_DRIVERS).default('auto'),
|
|
46
46
|
url: nonEmpty.optional(),
|
|
47
47
|
});
|
|
48
|
+
const rateLimitSchema = z.strictObject({
|
|
49
|
+
driver: z.enum(RATE_LIMIT_DRIVERS).default('auto'),
|
|
50
|
+
url: nonEmpty.optional(),
|
|
51
|
+
});
|
|
48
52
|
const storageSchema = z.strictObject({
|
|
49
53
|
driver: z.enum(STORAGE_DRIVERS).default('auto'),
|
|
50
54
|
bucket: nonEmpty.optional(),
|
|
@@ -82,6 +86,21 @@ const corsSchema = z
|
|
|
82
86
|
error: 'credentials cannot be combined with the "*" origin — every browser refuses that pair',
|
|
83
87
|
path: ['credentials'],
|
|
84
88
|
});
|
|
89
|
+
/**
|
|
90
|
+
* Audit-log retention (T09-01 / fiche 21 task 5's retention half —
|
|
91
|
+
* `AuditLog.prune()` existed since that fiche with no caller anywhere in
|
|
92
|
+
* the codebase).
|
|
93
|
+
*
|
|
94
|
+
* Absent `retainDays` — the default — means the log grows without bound,
|
|
95
|
+
* exactly the behaviour before this setting existed: unlike the 404 log or
|
|
96
|
+
* analytics events, an audit trail disappearing on a schedule nobody asked
|
|
97
|
+
* for is a worse default than a bigger database, so `cogenta serve` never
|
|
98
|
+
* purges unless a site opts in. `0` is the explicit, documented way to say
|
|
99
|
+
* "never purge" out loud rather than by omission.
|
|
100
|
+
*/
|
|
101
|
+
const auditRetentionSchema = z.strictObject({
|
|
102
|
+
retainDays: z.number().int().nonnegative().max(3650).optional(),
|
|
103
|
+
});
|
|
85
104
|
const securitySchema = z.strictObject({
|
|
86
105
|
cors: corsSchema.prefault({}),
|
|
87
106
|
/**
|
|
@@ -106,6 +125,26 @@ const securitySchema = z.strictObject({
|
|
|
106
125
|
hstsIncludeSubDomains: z.boolean().default(true),
|
|
107
126
|
/** How long a public page may be cached, in seconds. */
|
|
108
127
|
pageMaxAge: z.number().int().nonnegative().max(86_400).default(60),
|
|
128
|
+
audit: auditRetentionSchema.prefault({}),
|
|
129
|
+
});
|
|
130
|
+
/**
|
|
131
|
+
* The log of public URLs that answered a 404 (fiche 12 task 1).
|
|
132
|
+
*
|
|
133
|
+
* On by default, because an unresolved 404 is the daily nuisance no CMS
|
|
134
|
+
* should make an editor discover by luck. Everything it keeps is bounded on
|
|
135
|
+
* purpose: `maxPaths` is the hard cap on distinct paths tracked at once — an
|
|
136
|
+
* anonymous scanner can produce thousands of unique URLs a minute, and
|
|
137
|
+
* without a ceiling this log would be a disk-exhaustion vector any visitor
|
|
138
|
+
* could trigger — and `retainDays` is how long a path is kept since it was
|
|
139
|
+
* last requested. Neither an IP address nor a user agent is ever a field
|
|
140
|
+
* here, on any path: `AGENTS.md` § Logs forbids personal data outright, and
|
|
141
|
+
* the path plus its referrer already answer the only question this log
|
|
142
|
+
* exists for ("what should I redirect?").
|
|
143
|
+
*/
|
|
144
|
+
const notFoundLogSchema = z.strictObject({
|
|
145
|
+
enabled: z.boolean().default(true),
|
|
146
|
+
maxPaths: z.number().int().positive().max(100_000).default(2000),
|
|
147
|
+
retainDays: z.number().int().positive().max(3650).default(30),
|
|
109
148
|
});
|
|
110
149
|
/**
|
|
111
150
|
* Outbound content-lifecycle webhooks (L14 task 1).
|
|
@@ -120,6 +159,18 @@ const webhooksSchema = z.strictObject({
|
|
|
120
159
|
/** Absolute `http(s)` URLs. Empty — the default — means no webhook is sent. */
|
|
121
160
|
endpoints: z.array(z.url()).default([]),
|
|
122
161
|
});
|
|
162
|
+
/**
|
|
163
|
+
* Analytics events retention (fiche 27 task 3).
|
|
164
|
+
*
|
|
165
|
+
* 400 days by default — long enough that "compare this year to last year" (a
|
|
166
|
+
* real question a site owner asks) still has data on both sides, short
|
|
167
|
+
* enough that the events table cannot grow forever on a busy site. `cogenta
|
|
168
|
+
* serve` purges past this every day; there is no way to disable purging
|
|
169
|
+
* outright, only to choose how long to keep.
|
|
170
|
+
*/
|
|
171
|
+
const analyticsSchema = z.strictObject({
|
|
172
|
+
retainDays: z.number().int().positive().max(3650).default(400),
|
|
173
|
+
});
|
|
123
174
|
const embeddingsSchema = z.strictObject({
|
|
124
175
|
provider: z.enum(EMBEDDINGS_PROVIDERS).default('local'),
|
|
125
176
|
model: nonEmpty.default('all-MiniLM-L6-v2'),
|
|
@@ -151,6 +202,108 @@ const vectorSchema = z.strictObject({
|
|
|
151
202
|
path: nonEmpty.default('./.cogenta/vectors'),
|
|
152
203
|
table: nonEmpty.default('cogenta_vectors'),
|
|
153
204
|
});
|
|
205
|
+
/**
|
|
206
|
+
* Seller details for invoicing (contract E, ADR-0024).
|
|
207
|
+
*
|
|
208
|
+
* No defaults at all, unlike every other optional section: a guessed legal
|
|
209
|
+
* name or a blank address would produce an invoice that looks real and is
|
|
210
|
+
* not, which is worse than the feature being off. `cogenta serve` only mounts
|
|
211
|
+
* the invoice router once a site has filled this in.
|
|
212
|
+
*/
|
|
213
|
+
const billingSchema = z.strictObject({
|
|
214
|
+
legalName: nonEmpty,
|
|
215
|
+
address: z.array(nonEmpty).min(1),
|
|
216
|
+
taxId: nonEmpty.optional(),
|
|
217
|
+
footer: nonEmpty.optional(),
|
|
218
|
+
});
|
|
219
|
+
/**
|
|
220
|
+
* The scheduled-task clock (fiche 28 task 5).
|
|
221
|
+
*
|
|
222
|
+
* `'internal'` (the default) is `cogenta serve`'s own `setInterval` loop —
|
|
223
|
+
* the same shape every other recurring job in this codebase has always
|
|
224
|
+
* used, and the right choice for a process that stays up. `'external-cron'`
|
|
225
|
+
* is `docs/hebergement-mutualise.md`'s target: a host that recycles the
|
|
226
|
+
* process between requests, where an in-memory timer never fires reliably.
|
|
227
|
+
* In that mode `cogenta serve` registers every task but never ticks its own
|
|
228
|
+
* clock — only `cogenta cron`, called from the panel's own cron, drains due
|
|
229
|
+
* tasks. The admin screen reads this setting to say which mode is active,
|
|
230
|
+
* rather than guessing from whether a tick has happened recently.
|
|
231
|
+
*/
|
|
232
|
+
const schedulerSchema = z.strictObject({
|
|
233
|
+
mode: z.enum(['internal', 'external-cron']).default('internal'),
|
|
234
|
+
});
|
|
235
|
+
/**
|
|
236
|
+
* Scheduled full-site backups, riding the same clock as every other
|
|
237
|
+
* maintenance task (fiche 28 task 1's "sauvegarde planifiée", reusing
|
|
238
|
+
* `@cogenta/export`'s `createBackup` — the exact function `cogenta backup
|
|
239
|
+
* create` already calls by hand). Off by default: a backup file is
|
|
240
|
+
* unbounded disk usage a site did not ask for, and `dir` defaults to
|
|
241
|
+
* `.cogenta/backups` — the same directory the manual command writes to, so
|
|
242
|
+
* `cogenta backup list` shows scheduled and manual backups side by side.
|
|
243
|
+
*/
|
|
244
|
+
const backupSchema = z.strictObject({
|
|
245
|
+
enabled: z.boolean().default(false),
|
|
246
|
+
intervalHours: z
|
|
247
|
+
.number()
|
|
248
|
+
.int()
|
|
249
|
+
.positive()
|
|
250
|
+
.max(24 * 30)
|
|
251
|
+
.default(24),
|
|
252
|
+
/** Files kept before the oldest is pruned. */
|
|
253
|
+
keep: z.number().int().positive().max(365).default(10),
|
|
254
|
+
dir: nonEmpty.default('.cogenta/backups'),
|
|
255
|
+
});
|
|
256
|
+
/**
|
|
257
|
+
* The writing assistant's spending cap (fiche 30 task 3).
|
|
258
|
+
*
|
|
259
|
+
* A non-null default rather than "unlimited": the lot's own pitfall is exact
|
|
260
|
+
* — "le coût est invisible jusqu'à la facture", and a service billed per token
|
|
261
|
+
* left uncapped by default is the wrong default for a CMS that ships with AI
|
|
262
|
+
* off. One million tokens a month is generous for a single site's editors
|
|
263
|
+
* while still being a real ceiling, not a decoration.
|
|
264
|
+
*/
|
|
265
|
+
const assistantSchema = z.strictObject({
|
|
266
|
+
monthlyTokenLimit: z.number().int().positive().default(1_000_000),
|
|
267
|
+
});
|
|
268
|
+
/**
|
|
269
|
+
* OpenTelemetry tracing (fiche L22 task 5). No `otlpHeaders` field, on
|
|
270
|
+
* purpose (rule R7, `SECRET_KEYS` in `env.ts` refuses it before this schema
|
|
271
|
+
* even parses) — those come from `COGENTA_OTLP_HEADERS`/
|
|
272
|
+
* `OTEL_EXPORTER_OTLP_HEADERS` only. `otlpEndpoint` absent means local
|
|
273
|
+
* collection only: the recent-events buffer behind the admin's
|
|
274
|
+
* "Exploitation" screen always works with nothing configured here (R1).
|
|
275
|
+
*/
|
|
276
|
+
const observabilitySchema = z.strictObject({
|
|
277
|
+
serviceName: nonEmpty.default('cogenta'),
|
|
278
|
+
otlpEndpoint: z.url().optional(),
|
|
279
|
+
});
|
|
280
|
+
/**
|
|
281
|
+
* Contract E's payment gateway choice (fiche 34 task 3).
|
|
282
|
+
*
|
|
283
|
+
* No `secretKey` or `webhookSecret` field, on purpose (rule R7, same shape as
|
|
284
|
+
* `llmSchema`'s missing `apiKey`): Stripe's credentials come from
|
|
285
|
+
* `COGENTA_PAYMENT_STRIPE_SECRET_KEY`/`COGENTA_PAYMENT_STRIPE_WEBHOOK_SECRET`
|
|
286
|
+
* only, and `SECRET_KEYS` (`env.ts`) refuses either one written here before
|
|
287
|
+
* this schema is even parsed. `testMode` defaults `true`: a shop that has not
|
|
288
|
+
* deliberately flipped it to production cannot silently start taking real
|
|
289
|
+
* money, matching the fiche's "le mode test doit être criant".
|
|
290
|
+
*/
|
|
291
|
+
const paymentSchema = z.strictObject({
|
|
292
|
+
driver: z.enum(PAYMENT_DRIVERS).default('auto'),
|
|
293
|
+
testMode: z.boolean().default(true),
|
|
294
|
+
manualInstructions: nonEmpty.optional(),
|
|
295
|
+
});
|
|
296
|
+
/**
|
|
297
|
+
* Google Search Console OAuth (fiche 70 task 4, ADR-0032). No fields at all —
|
|
298
|
+
* the app's own OAuth client id/secret are both secrets (rule R7) and come
|
|
299
|
+
* from `COGENTA_SEARCH_CONSOLE_CLIENT_ID`/`COGENTA_SEARCH_CONSOLE_CLIENT_SECRET`
|
|
300
|
+
* only, refused here by `SECRET_KEYS` (`env.ts`) exactly like `payment`'s own
|
|
301
|
+
* Stripe/PayPal keys. Everything per-site — whether a site has connected, and
|
|
302
|
+
* which GSC property it queries — lives in the database
|
|
303
|
+
* (`@cogenta/schema`'s `search-console-store.ts`), never here: this section
|
|
304
|
+
* exists only so the *installation* can offer the connector at all.
|
|
305
|
+
*/
|
|
306
|
+
const searchConsoleSchema = z.strictObject({});
|
|
154
307
|
// `prefault` rather than `default`: an omitted section is parsed as `{}` so the
|
|
155
308
|
// per-field defaults inside it apply, instead of being replaced wholesale.
|
|
156
309
|
export const configSchema = z.strictObject({
|
|
@@ -158,13 +311,23 @@ export const configSchema = z.strictObject({
|
|
|
158
311
|
database: databaseSchema,
|
|
159
312
|
cache: cacheSchema.prefault({}),
|
|
160
313
|
queue: queueSchema.prefault({}),
|
|
314
|
+
rateLimit: rateLimitSchema.prefault({}),
|
|
161
315
|
storage: storageSchema.prefault({}),
|
|
162
316
|
security: securitySchema.prefault({}),
|
|
317
|
+
notFoundLog: notFoundLogSchema.prefault({}),
|
|
163
318
|
webhooks: webhooksSchema.prefault({}),
|
|
319
|
+
analytics: analyticsSchema.prefault({}),
|
|
164
320
|
llm: llmSchema.optional(),
|
|
165
321
|
embeddings: embeddingsSchema.prefault({}),
|
|
166
322
|
imageGeneration: imageGenerationSchema.optional(),
|
|
167
323
|
vector: vectorSchema.prefault({}),
|
|
324
|
+
billing: billingSchema.optional(),
|
|
325
|
+
scheduler: schedulerSchema.prefault({}),
|
|
326
|
+
backup: backupSchema.prefault({}),
|
|
327
|
+
assistant: assistantSchema.prefault({}),
|
|
328
|
+
payment: paymentSchema.prefault({}),
|
|
329
|
+
observability: observabilitySchema.prefault({}),
|
|
330
|
+
searchConsole: searchConsoleSchema.prefault({}),
|
|
168
331
|
});
|
|
169
332
|
/**
|
|
170
333
|
* Renders Zod issues as `field: reason`, one per line, so the user sees every
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAA;AAEnB,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAElC,gFAAgF;AAChF,8EAA8E;AAC9E,uCAAuC;AACvC,MAAM,UAAU,GAAG,CAAC;KACjB,YAAY,CAAC;IACZ,IAAI,EAAE,QAAQ;IACd,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE;IACZ,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;IACjD,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC;;;;;;;;;OASG;IACH,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,UAAU,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC;SACzF,OAAO,CAAC,MAAM,CAAC;CACnB,CAAC;KACD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;IAC3D,KAAK,EAAE,qDAAqD;IAC5D,IAAI,EAAE,CAAC,eAAe,CAAC;CACxB,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC,CAAC,YAAY,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE;IAC3C,GAAG,EAAE,QAAQ;IACb,qEAAqE;IACrE,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1D,CAAC,CAAA;AAEF,MAAM,WAAW,GAAG,CAAC,CAAC,YAAY,CAAC;IACjC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE;IACxB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,WAAW,GAAG,CAAC,CAAC,YAAY,CAAC;IACjC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE;CACzB,CAAC,CAAA;AAEF,MAAM,aAAa,GAAG,CAAC,CAAC,YAAY,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC/C,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE;IAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE;IAC7B,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC;IAC1C,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;CACpC,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC;IAC/B,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,CAAC;KACjB,YAAY,CAAC;IACZ,mGAAmG;IACnG,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrF,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IACrE,kFAAkF;IAClF,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACvC,+CAA+C;IAC/C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;CAChE,CAAC;KACD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE;IACnE,KAAK,EAAE,sFAAsF;IAC7F,IAAI,EAAE,CAAC,aAAa,CAAC;CACtB,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC,CAAC,YAAY,CAAC;IACpC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC7B;;;;;;;;OAQG;IACH,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrD;;;;;;;OAOG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,wDAAwD;IACxD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects, but never blocks, the two secret-hygiene gaps fiche 23 names as
|
|
3
|
+
* open (audit follow-up to L10 task 6 / `docs/hebergement-mutualise.md`):
|
|
4
|
+
* `create-cogenta` used to write a database URL — password included — into
|
|
5
|
+
* `cogenta.config.mjs` in the clear, and the generated `.env` (which holds
|
|
6
|
+
* `COGENTA_AUTH_SIGNING_KEY`) was written without a restrictive file mode, so
|
|
7
|
+
* another tenant on shared hosting could read it.
|
|
8
|
+
*
|
|
9
|
+
* `SECRET_KEYS` (`env.ts`) cannot simply gain `database.url`: unlike an API
|
|
10
|
+
* key, a database URL is legitimately present in the file for the common
|
|
11
|
+
* case — a SQLite path, or a Postgres URL with no password at all (peer
|
|
12
|
+
* trust, a local dev server) — so refusing it outright at `resolveConfig`
|
|
13
|
+
* would break every SQLite site, which is Cogenta's zero-config default.
|
|
14
|
+
* What *is* always wrong is a URL that embeds real credentials: that half is
|
|
15
|
+
* detected here and **surfaced**, on the ops-settings mirror (fiche 23 task
|
|
16
|
+
* 5's literal ask — "détecter et signaler"), never turned into a hard
|
|
17
|
+
* refusal that would regress a legitimate config.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* `true` when `value` parses as a URL carrying a non-empty username or
|
|
21
|
+
* password. A bare path (`./data.db`, `:memory:`) or a URL with no userinfo
|
|
22
|
+
* (`postgres://localhost/db`) is `false` — there is nothing secret to leak.
|
|
23
|
+
*/
|
|
24
|
+
export declare function urlHasEmbeddedCredentials(value: string): boolean;
|
|
25
|
+
export interface SecretHygieneReport {
|
|
26
|
+
/** `true` when the raw config file sets `database.url` to a URL carrying real credentials. */
|
|
27
|
+
readonly databaseUrlHasCredentialsInFile: boolean;
|
|
28
|
+
/** The `.env` file `loadConfig` looked for next to the config, or `null` when there is no config file. */
|
|
29
|
+
readonly envFilePath: string | null;
|
|
30
|
+
/**
|
|
31
|
+
* `true` when `.env` grants read access to the file's group or to anyone
|
|
32
|
+
* else on the machine — exactly what a shared-hosting neighbour would use.
|
|
33
|
+
* `null` when there is no `.env` file, or the platform's permission bits
|
|
34
|
+
* are not the POSIX ones this check reads (win32).
|
|
35
|
+
*/
|
|
36
|
+
readonly envFileReadableByOthers: boolean | null;
|
|
37
|
+
}
|
|
38
|
+
/** Reads the raw, unresolved `database.url` a config file declares, or `undefined` for none. */
|
|
39
|
+
export declare function rawDatabaseUrl(input: unknown): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* `true` when `mode` (a POSIX file mode, as `fs.Stats.mode` reports it)
|
|
42
|
+
* grants read access to its group or to "other" — the two bits that matter
|
|
43
|
+
* on a shared host, where every tenant's process runs as a different,
|
|
44
|
+
* unprivileged user. Pure and platform-independent so the actual security
|
|
45
|
+
* arithmetic — which bits mean "someone else can read this" — is tested
|
|
46
|
+
* directly, without a real file or a real POSIX host.
|
|
47
|
+
*/
|
|
48
|
+
export declare function hasGroupOrOtherRead(mode: number): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Builds the report `loadConfig` attaches to `LoadedConfig`. `rawConfig` is
|
|
51
|
+
* the *unresolved* file contents (before `resolveConfig` strips anything) —
|
|
52
|
+
* the same object `findSecretsInFile` already inspects.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildSecretHygieneReport(rawConfig: unknown, envFilePath: string | null, envFileExists: boolean): Promise<SecretHygieneReport>;
|
|
55
|
+
//# sourceMappingURL=secret-hygiene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-hygiene.d.ts","sourceRoot":"","sources":["../../src/config/secret-hygiene.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOhE;AAED,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,QAAQ,CAAC,+BAA+B,EAAE,OAAO,CAAA;IACjD,0GAA0G;IAC1G,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,uBAAuB,EAAE,OAAO,GAAG,IAAI,CAAA;CACjD;AAMD,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAMjE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGzD;AAqBD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,OAAO,EAClB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,mBAAmB,CAAC,CAQ9B"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
/**
|
|
4
|
+
* Detects, but never blocks, the two secret-hygiene gaps fiche 23 names as
|
|
5
|
+
* open (audit follow-up to L10 task 6 / `docs/hebergement-mutualise.md`):
|
|
6
|
+
* `create-cogenta` used to write a database URL — password included — into
|
|
7
|
+
* `cogenta.config.mjs` in the clear, and the generated `.env` (which holds
|
|
8
|
+
* `COGENTA_AUTH_SIGNING_KEY`) was written without a restrictive file mode, so
|
|
9
|
+
* another tenant on shared hosting could read it.
|
|
10
|
+
*
|
|
11
|
+
* `SECRET_KEYS` (`env.ts`) cannot simply gain `database.url`: unlike an API
|
|
12
|
+
* key, a database URL is legitimately present in the file for the common
|
|
13
|
+
* case — a SQLite path, or a Postgres URL with no password at all (peer
|
|
14
|
+
* trust, a local dev server) — so refusing it outright at `resolveConfig`
|
|
15
|
+
* would break every SQLite site, which is Cogenta's zero-config default.
|
|
16
|
+
* What *is* always wrong is a URL that embeds real credentials: that half is
|
|
17
|
+
* detected here and **surfaced**, on the ops-settings mirror (fiche 23 task
|
|
18
|
+
* 5's literal ask — "détecter et signaler"), never turned into a hard
|
|
19
|
+
* refusal that would regress a legitimate config.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* `true` when `value` parses as a URL carrying a non-empty username or
|
|
23
|
+
* password. A bare path (`./data.db`, `:memory:`) or a URL with no userinfo
|
|
24
|
+
* (`postgres://localhost/db`) is `false` — there is nothing secret to leak.
|
|
25
|
+
*/
|
|
26
|
+
export function urlHasEmbeddedCredentials(value) {
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(value);
|
|
29
|
+
return url.username !== '' || url.password !== '';
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function isPlainObject(value) {
|
|
36
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
/** Reads the raw, unresolved `database.url` a config file declares, or `undefined` for none. */
|
|
39
|
+
export function rawDatabaseUrl(input) {
|
|
40
|
+
if (!isPlainObject(input))
|
|
41
|
+
return undefined;
|
|
42
|
+
const database = input['database'];
|
|
43
|
+
if (!isPlainObject(database))
|
|
44
|
+
return undefined;
|
|
45
|
+
const url = database['url'];
|
|
46
|
+
return typeof url === 'string' ? url : undefined;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* `true` when `mode` (a POSIX file mode, as `fs.Stats.mode` reports it)
|
|
50
|
+
* grants read access to its group or to "other" — the two bits that matter
|
|
51
|
+
* on a shared host, where every tenant's process runs as a different,
|
|
52
|
+
* unprivileged user. Pure and platform-independent so the actual security
|
|
53
|
+
* arithmetic — which bits mean "someone else can read this" — is tested
|
|
54
|
+
* directly, without a real file or a real POSIX host.
|
|
55
|
+
*/
|
|
56
|
+
export function hasGroupOrOtherRead(mode) {
|
|
57
|
+
// group-read (0o040) or other-read (0o004).
|
|
58
|
+
return (mode & 0o044) !== 0;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* `path`'s mode, read from disk, or `null` on a platform whose permission
|
|
62
|
+
* model this check does not understand (win32 — ACLs, not POSIX rwx bits;
|
|
63
|
+
* Node synthesises a `mode` there rather than reporting a real one, and
|
|
64
|
+
* reporting `false` would claim a guarantee that platform cannot make) or
|
|
65
|
+
* when the file cannot be stat'd at all. Read-only by design: fixing the
|
|
66
|
+
* mode is `create-cogenta`'s job at write time (`scaffold.ts`), not
|
|
67
|
+
* something a running server silently changes under an operator's file.
|
|
68
|
+
*/
|
|
69
|
+
async function isReadableByOthers(path) {
|
|
70
|
+
if (process.platform === 'win32')
|
|
71
|
+
return null;
|
|
72
|
+
try {
|
|
73
|
+
const info = await stat(path);
|
|
74
|
+
return hasGroupOrOtherRead(info.mode);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Builds the report `loadConfig` attaches to `LoadedConfig`. `rawConfig` is
|
|
82
|
+
* the *unresolved* file contents (before `resolveConfig` strips anything) —
|
|
83
|
+
* the same object `findSecretsInFile` already inspects.
|
|
84
|
+
*/
|
|
85
|
+
export async function buildSecretHygieneReport(rawConfig, envFilePath, envFileExists) {
|
|
86
|
+
const url = rawDatabaseUrl(rawConfig);
|
|
87
|
+
const path = envFileExists ? envFilePath : null;
|
|
88
|
+
return {
|
|
89
|
+
databaseUrlHasCredentialsInFile: url !== undefined && urlHasEmbeddedCredentials(url),
|
|
90
|
+
envFilePath: path,
|
|
91
|
+
envFileReadableByOthers: path === null ? null : await isReadableByOthers(path),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=secret-hygiene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-hygiene.js","sourceRoot":"","sources":["../../src/config/secret-hygiene.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACvC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1B,OAAO,GAAG,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAgBD,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;IAClC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3B,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;AAClD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,4CAA4C;IAC5C,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,kBAAkB,CAAC,IAAY;IAC5C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAA;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7B,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,SAAkB,EAClB,WAA0B,EAC1B,aAAsB;IAEtB,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA;IAC/C,OAAO;QACL,+BAA+B,EAAE,GAAG,KAAK,SAAS,IAAI,yBAAyB,CAAC,GAAG,CAAC;QACpF,WAAW,EAAE,IAAI;QACjB,uBAAuB,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC;KAC/E,CAAA;AACH,CAAC"}
|