@kelpie/server 0.5.2 → 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/README.md +5 -2
- package/dist/index.d.ts +17 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/actor.d.ts +9 -1
- package/dist/lib/actor.d.ts.map +1 -1
- package/dist/lib/actor.js +13 -0
- package/dist/lib/actor.js.map +1 -1
- package/dist/lib/config.d.ts +44 -6
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +9 -5
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/email.d.ts +15 -63
- package/dist/lib/email.d.ts.map +1 -1
- package/dist/lib/email.js +13 -65
- package/dist/lib/email.js.map +1 -1
- package/dist/lib/fromEnv.d.ts +60 -0
- package/dist/lib/fromEnv.d.ts.map +1 -0
- package/dist/lib/fromEnv.js +94 -0
- package/dist/lib/fromEnv.js.map +1 -0
- package/dist/lib/ids.d.ts +6 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +6 -0
- package/dist/lib/ids.js.map +1 -1
- package/dist/lib/kelpieConfigFile.d.ts +123 -0
- package/dist/lib/kelpieConfigFile.d.ts.map +1 -0
- package/dist/lib/kelpieConfigFile.js +111 -0
- package/dist/lib/kelpieConfigFile.js.map +1 -0
- package/dist/lib/logger.d.ts +38 -7
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +58 -20
- package/dist/lib/logger.js.map +1 -1
- package/dist/modules/agent-tasks/index.d.ts.map +1 -1
- package/dist/modules/agent-tasks/index.js +4 -1
- package/dist/modules/agent-tasks/index.js.map +1 -1
- package/dist/modules/agent-tasks/prompt.d.ts +36 -6
- package/dist/modules/agent-tasks/prompt.d.ts.map +1 -1
- package/dist/modules/agent-tasks/prompt.js +33 -4
- package/dist/modules/agent-tasks/prompt.js.map +1 -1
- package/dist/modules/agent-tasks/service.d.ts.map +1 -1
- package/dist/modules/agent-tasks/service.js +3 -2
- package/dist/modules/agent-tasks/service.js.map +1 -1
- package/dist/modules/agent-tasks/wire.d.ts +11 -0
- package/dist/modules/agent-tasks/wire.d.ts.map +1 -1
- package/dist/modules/agent-tasks/wire.js +1 -0
- package/dist/modules/agent-tasks/wire.js.map +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +8 -7
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/companies/events.d.ts +22 -0
- package/dist/modules/companies/events.d.ts.map +1 -0
- package/dist/modules/companies/events.js +8 -0
- package/dist/modules/companies/events.js.map +1 -0
- package/dist/modules/companies/index.d.ts.map +1 -1
- package/dist/modules/companies/index.js +2 -0
- package/dist/modules/companies/index.js.map +1 -1
- package/dist/modules/companies/service.d.ts +1 -0
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +8 -11
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +4 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/deals/events.d.ts +31 -0
- package/dist/modules/deals/events.d.ts.map +1 -0
- package/dist/modules/deals/events.js +12 -0
- package/dist/modules/deals/events.js.map +1 -0
- package/dist/modules/deals/index.d.ts.map +1 -1
- package/dist/modules/deals/index.js +2 -0
- package/dist/modules/deals/index.js.map +1 -1
- package/dist/modules/deals/service.d.ts +1 -0
- package/dist/modules/deals/service.d.ts.map +1 -1
- package/dist/modules/deals/service.js +9 -18
- package/dist/modules/deals/service.js.map +1 -1
- package/dist/modules/decisions/events.d.ts +21 -0
- package/dist/modules/decisions/events.d.ts.map +1 -0
- package/dist/modules/decisions/events.js +11 -0
- package/dist/modules/decisions/events.js.map +1 -0
- package/dist/modules/decisions/index.d.ts.map +1 -1
- package/dist/modules/decisions/index.js +2 -0
- package/dist/modules/decisions/index.js.map +1 -1
- package/dist/modules/decisions/service.d.ts +1 -0
- package/dist/modules/decisions/service.d.ts.map +1 -1
- package/dist/modules/decisions/service.js +4 -7
- package/dist/modules/decisions/service.js.map +1 -1
- package/dist/modules/forms/events.d.ts +37 -0
- package/dist/modules/forms/events.d.ts.map +1 -0
- package/dist/modules/forms/events.js +15 -0
- package/dist/modules/forms/events.js.map +1 -0
- package/dist/modules/forms/index.d.ts.map +1 -1
- package/dist/modules/forms/index.js +2 -0
- package/dist/modules/forms/index.js.map +1 -1
- package/dist/modules/forms/service.d.ts +1 -0
- package/dist/modules/forms/service.d.ts.map +1 -1
- package/dist/modules/forms/service.js +8 -11
- package/dist/modules/forms/service.js.map +1 -1
- package/dist/modules/forms/submission.d.ts +5 -0
- package/dist/modules/forms/submission.d.ts.map +1 -1
- package/dist/modules/forms/submission.js +54 -28
- package/dist/modules/forms/submission.js.map +1 -1
- package/dist/modules/handbook/events.d.ts +28 -0
- package/dist/modules/handbook/events.d.ts.map +1 -0
- package/dist/modules/handbook/events.js +14 -0
- package/dist/modules/handbook/events.js.map +1 -0
- package/dist/modules/handbook/index.d.ts.map +1 -1
- package/dist/modules/handbook/index.js +2 -0
- package/dist/modules/handbook/index.js.map +1 -1
- package/dist/modules/handbook/service.d.ts +1 -0
- package/dist/modules/handbook/service.d.ts.map +1 -1
- package/dist/modules/handbook/service.js +8 -15
- package/dist/modules/handbook/service.js.map +1 -1
- package/dist/modules/hiring/candidates.d.ts +1 -0
- package/dist/modules/hiring/candidates.d.ts.map +1 -1
- package/dist/modules/hiring/candidates.js +8 -11
- package/dist/modules/hiring/candidates.js.map +1 -1
- package/dist/modules/hiring/events.d.ts +35 -0
- package/dist/modules/hiring/events.d.ts.map +1 -0
- package/dist/modules/hiring/events.js +11 -0
- package/dist/modules/hiring/events.js.map +1 -0
- package/dist/modules/hiring/index.d.ts.map +1 -1
- package/dist/modules/hiring/index.js +2 -0
- package/dist/modules/hiring/index.js.map +1 -1
- package/dist/modules/hiring/roles.d.ts +1 -0
- package/dist/modules/hiring/roles.d.ts.map +1 -1
- package/dist/modules/hiring/roles.js +8 -11
- package/dist/modules/hiring/roles.js.map +1 -1
- package/dist/modules/import-export/events.d.ts +22 -0
- package/dist/modules/import-export/events.d.ts.map +1 -0
- package/dist/modules/import-export/events.js +12 -0
- package/dist/modules/import-export/events.js.map +1 -0
- package/dist/modules/import-export/index.d.ts.map +1 -1
- package/dist/modules/import-export/index.js +2 -0
- package/dist/modules/import-export/index.js.map +1 -1
- package/dist/modules/import-export/service.d.ts +5 -0
- package/dist/modules/import-export/service.d.ts.map +1 -1
- package/dist/modules/import-export/service.js +53 -14
- package/dist/modules/import-export/service.js.map +1 -1
- package/dist/modules/notes/events.d.ts +22 -0
- package/dist/modules/notes/events.d.ts.map +1 -0
- package/dist/modules/notes/events.js +12 -0
- package/dist/modules/notes/events.js.map +1 -0
- package/dist/modules/notes/index.d.ts.map +1 -1
- package/dist/modules/notes/index.js +2 -0
- package/dist/modules/notes/index.js.map +1 -1
- package/dist/modules/notes/service.d.ts +1 -0
- package/dist/modules/notes/service.d.ts.map +1 -1
- package/dist/modules/notes/service.js +4 -7
- package/dist/modules/notes/service.js.map +1 -1
- package/dist/modules/opportunities/events.d.ts +31 -0
- package/dist/modules/opportunities/events.d.ts.map +1 -0
- package/dist/modules/opportunities/events.js +12 -0
- package/dist/modules/opportunities/events.js.map +1 -0
- package/dist/modules/opportunities/index.d.ts.map +1 -1
- package/dist/modules/opportunities/index.js +2 -0
- package/dist/modules/opportunities/index.js.map +1 -1
- package/dist/modules/opportunities/service.d.ts +1 -0
- package/dist/modules/opportunities/service.d.ts.map +1 -1
- package/dist/modules/opportunities/service.js +9 -18
- package/dist/modules/opportunities/service.js.map +1 -1
- package/dist/modules/partnerships/events.d.ts +31 -0
- package/dist/modules/partnerships/events.d.ts.map +1 -0
- package/dist/modules/partnerships/events.js +12 -0
- package/dist/modules/partnerships/events.js.map +1 -0
- package/dist/modules/partnerships/index.d.ts.map +1 -1
- package/dist/modules/partnerships/index.js +2 -0
- package/dist/modules/partnerships/index.js.map +1 -1
- package/dist/modules/partnerships/service.d.ts +1 -0
- package/dist/modules/partnerships/service.d.ts.map +1 -1
- package/dist/modules/partnerships/service.js +9 -18
- package/dist/modules/partnerships/service.js.map +1 -1
- package/dist/modules/people/events.d.ts +28 -0
- package/dist/modules/people/events.d.ts.map +1 -0
- package/dist/modules/people/events.js +18 -0
- package/dist/modules/people/events.js.map +1 -0
- package/dist/modules/people/index.d.ts.map +1 -1
- package/dist/modules/people/index.js +2 -0
- package/dist/modules/people/index.js.map +1 -1
- package/dist/modules/people/service.d.ts +1 -0
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +8 -11
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/pipelines/service.d.ts +4 -0
- package/dist/modules/pipelines/service.d.ts.map +1 -1
- package/dist/modules/pipelines/service.js +31 -8
- package/dist/modules/pipelines/service.js.map +1 -1
- package/dist/modules/plans/events.d.ts +21 -0
- package/dist/modules/plans/events.d.ts.map +1 -0
- package/dist/modules/plans/events.js +11 -0
- package/dist/modules/plans/events.js.map +1 -0
- package/dist/modules/plans/index.d.ts.map +1 -1
- package/dist/modules/plans/index.js +2 -0
- package/dist/modules/plans/index.js.map +1 -1
- package/dist/modules/plans/service.d.ts +1 -0
- package/dist/modules/plans/service.d.ts.map +1 -1
- package/dist/modules/plans/service.js +6 -14
- package/dist/modules/plans/service.js.map +1 -1
- package/dist/modules/positions/events.d.ts +22 -0
- package/dist/modules/positions/events.d.ts.map +1 -0
- package/dist/modules/positions/events.js +8 -0
- package/dist/modules/positions/events.js.map +1 -0
- package/dist/modules/positions/index.d.ts.map +1 -1
- package/dist/modules/positions/index.js +2 -0
- package/dist/modules/positions/index.js.map +1 -1
- package/dist/modules/positions/service.d.ts +1 -0
- package/dist/modules/positions/service.d.ts.map +1 -1
- package/dist/modules/positions/service.js +8 -11
- package/dist/modules/positions/service.js.map +1 -1
- package/dist/modules/raises/events.d.ts +31 -0
- package/dist/modules/raises/events.d.ts.map +1 -0
- package/dist/modules/raises/events.js +12 -0
- package/dist/modules/raises/events.js.map +1 -0
- package/dist/modules/raises/index.d.ts.map +1 -1
- package/dist/modules/raises/index.js +2 -0
- package/dist/modules/raises/index.js.map +1 -1
- package/dist/modules/raises/service.d.ts +1 -0
- package/dist/modules/raises/service.d.ts.map +1 -1
- package/dist/modules/raises/service.js +9 -18
- package/dist/modules/raises/service.js.map +1 -1
- package/dist/modules/reseal.d.ts +55 -0
- package/dist/modules/reseal.d.ts.map +1 -1
- package/dist/modules/reseal.js +90 -1
- package/dist/modules/reseal.js.map +1 -1
- package/dist/modules/smtp-email/index.d.ts +69 -0
- package/dist/modules/smtp-email/index.d.ts.map +1 -0
- package/dist/modules/smtp-email/index.js +82 -0
- package/dist/modules/smtp-email/index.js.map +1 -0
- package/dist/modules/webhooks/index.d.ts.map +1 -1
- package/dist/modules/webhooks/index.js +5 -1
- package/dist/modules/webhooks/index.js.map +1 -1
- package/dist/modules/webhooks/payloads.d.ts +22 -7
- package/dist/modules/webhooks/payloads.d.ts.map +1 -1
- package/dist/modules/webhooks/payloads.js +63 -44
- package/dist/modules/webhooks/payloads.js.map +1 -1
- package/dist/modules/workspace/events.d.ts +52 -0
- package/dist/modules/workspace/events.d.ts.map +1 -0
- package/dist/modules/workspace/events.js +16 -0
- package/dist/modules/workspace/events.js.map +1 -0
- package/dist/modules/workspace/index.d.ts.map +1 -1
- package/dist/modules/workspace/index.js +6 -2
- package/dist/modules/workspace/index.js.map +1 -1
- package/dist/modules/workspace/service.d.ts +1 -0
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +13 -15
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/runtime/events.d.ts +86 -108
- package/dist/runtime/events.d.ts.map +1 -1
- package/dist/runtime/events.js +123 -52
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/module.d.ts +54 -2
- package/dist/runtime/module.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts +23 -0
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/registry.js +102 -2
- package/dist/runtime/registry.js.map +1 -1
- package/dist/runtime/transaction.d.ts +29 -4
- package/dist/runtime/transaction.d.ts.map +1 -1
- package/dist/runtime/transaction.js +48 -7
- package/dist/runtime/transaction.js.map +1 -1
- package/dist/testing/app.d.ts.map +1 -1
- package/dist/testing/app.js +11 -3
- package/dist/testing/app.js.map +1 -1
- package/dist/testing/database.d.ts.map +1 -1
- package/dist/testing/database.js +6 -3
- package/dist/testing/database.js.map +1 -1
- package/dist/testing/services.d.ts +21 -1
- package/dist/testing/services.d.ts.map +1 -1
- package/dist/testing/services.js +20 -5
- package/dist/testing/services.js.map +1 -1
- package/package.json +5 -2
- package/src/index.ts +44 -9
- package/src/lib/actor.ts +15 -1
- package/src/lib/config.ts +56 -7
- package/src/lib/email.ts +22 -92
- package/src/lib/fromEnv.ts +143 -0
- package/src/lib/ids.ts +6 -0
- package/src/lib/kelpieConfigFile.ts +283 -0
- package/src/lib/logger.ts +92 -34
- package/src/modules/agent-tasks/index.ts +4 -1
- package/src/modules/agent-tasks/prompt.ts +57 -9
- package/src/modules/agent-tasks/service.ts +3 -2
- package/src/modules/agent-tasks/wire.ts +12 -0
- package/src/modules/auth/index.ts +11 -9
- package/src/modules/companies/events.ts +25 -0
- package/src/modules/companies/index.ts +2 -0
- package/src/modules/companies/service.ts +8 -11
- package/src/modules/core.ts +4 -0
- package/src/modules/deals/events.ts +34 -0
- package/src/modules/deals/index.ts +2 -0
- package/src/modules/deals/service.ts +17 -18
- package/src/modules/decisions/events.ts +24 -0
- package/src/modules/decisions/index.ts +2 -0
- package/src/modules/decisions/service.ts +8 -7
- package/src/modules/forms/events.ts +37 -0
- package/src/modules/forms/index.ts +2 -0
- package/src/modules/forms/service.ts +12 -11
- package/src/modules/forms/submission.ts +80 -29
- package/src/modules/handbook/events.ts +31 -0
- package/src/modules/handbook/index.ts +2 -0
- package/src/modules/handbook/service.ts +8 -15
- package/src/modules/hiring/candidates.ts +8 -11
- package/src/modules/hiring/events.ts +36 -0
- package/src/modules/hiring/index.ts +2 -0
- package/src/modules/hiring/roles.ts +8 -11
- package/src/modules/import-export/events.ts +25 -0
- package/src/modules/import-export/index.ts +2 -0
- package/src/modules/import-export/service.ts +83 -15
- package/src/modules/notes/events.ts +25 -0
- package/src/modules/notes/index.ts +2 -0
- package/src/modules/notes/service.ts +8 -7
- package/src/modules/opportunities/events.ts +34 -0
- package/src/modules/opportunities/index.ts +2 -0
- package/src/modules/opportunities/service.ts +17 -18
- package/src/modules/partnerships/events.ts +34 -0
- package/src/modules/partnerships/index.ts +2 -0
- package/src/modules/partnerships/service.ts +17 -18
- package/src/modules/people/events.ts +36 -0
- package/src/modules/people/index.ts +2 -0
- package/src/modules/people/service.ts +97 -87
- package/src/modules/pipelines/service.ts +47 -8
- package/src/modules/plans/events.ts +24 -0
- package/src/modules/plans/index.ts +2 -0
- package/src/modules/plans/service.ts +14 -14
- package/src/modules/positions/events.ts +25 -0
- package/src/modules/positions/index.ts +2 -0
- package/src/modules/positions/service.ts +8 -11
- package/src/modules/raises/events.ts +34 -0
- package/src/modules/raises/index.ts +2 -0
- package/src/modules/raises/service.ts +17 -18
- package/src/modules/reseal.ts +144 -1
- package/src/modules/smtp-email/index.ts +119 -0
- package/src/modules/webhooks/index.ts +5 -1
- package/src/modules/webhooks/payloads.ts +94 -48
- package/src/modules/workspace/events.ts +46 -0
- package/src/modules/workspace/index.ts +6 -2
- package/src/modules/workspace/service.ts +37 -15
- package/src/runtime/events.ts +268 -107
- package/src/runtime/module.ts +55 -2
- package/src/runtime/registry.ts +169 -1
- package/src/runtime/transaction.ts +94 -17
- package/src/testing/app.ts +11 -3
- package/src/testing/database.ts +6 -3
- package/src/testing/services.ts +34 -5
package/src/index.ts
CHANGED
|
@@ -7,6 +7,21 @@ export type { WebBundleOptions } from './webBundle.ts'
|
|
|
7
7
|
export { ConfigurationError, loadConfig } from './lib/config.ts'
|
|
8
8
|
export type { Environment, KelpieConfig, LogLevel, RuntimeMode } from './lib/config.ts'
|
|
9
9
|
|
|
10
|
+
export { fromEnv, isFromEnvMarker, resolveMarker, resolveMarkers } from './lib/fromEnv.ts'
|
|
11
|
+
export type { ConfigValue, FromEnvMarker, FromEnvProblem, ResolveResult } from './lib/fromEnv.ts'
|
|
12
|
+
|
|
13
|
+
export { defineKelpieConfig, resolveKelpieConfig } from './lib/kelpieConfigFile.ts'
|
|
14
|
+
export type {
|
|
15
|
+
EmailInput,
|
|
16
|
+
KelpieConfigInput,
|
|
17
|
+
RateLimitBudgetInput,
|
|
18
|
+
RateLimitInput,
|
|
19
|
+
SecretEncryptionInput,
|
|
20
|
+
} from './lib/kelpieConfigFile.ts'
|
|
21
|
+
|
|
22
|
+
export { appUrlConfigSchema } from './lib/appUrl.ts'
|
|
23
|
+
export type { AppUrlConfig } from './lib/appUrl.ts'
|
|
24
|
+
|
|
10
25
|
export { resolveClientIpFrom } from './lib/clientIp.ts'
|
|
11
26
|
|
|
12
27
|
export { ModuleConfigFileError, readModuleConfigFile } from './lib/moduleConfig.ts'
|
|
@@ -23,9 +38,12 @@ export type { Database, DatabaseConnection, DatabaseProbe } from './lib/database
|
|
|
23
38
|
|
|
24
39
|
export * as schema from './schema/index.ts'
|
|
25
40
|
|
|
26
|
-
export {
|
|
41
|
+
export { createLogEmailSender, emailConfigSchema } from './lib/email.ts'
|
|
27
42
|
export type { EmailConfig, EmailMessage, EmailSender } from './lib/email.ts'
|
|
28
43
|
|
|
44
|
+
export { SMTP_EMAIL_PROVIDER, createSmtpEmailModule, createSmtpEmailSender } from './modules/smtp-email/index.ts'
|
|
45
|
+
export type { SmtpEmailConfig, SmtpEmailModuleOptions, SmtpTransport } from './modules/smtp-email/index.ts'
|
|
46
|
+
|
|
29
47
|
export { MINIMUM_PASSWORD_LENGTH, hashPassword, isPasswordStrongEnough, verifyPassword } from './lib/passwords.ts'
|
|
30
48
|
export { generateToken, hashToken, tokenHashesMatch } from './lib/tokens.ts'
|
|
31
49
|
|
|
@@ -49,8 +67,13 @@ export type { ErrorBody, ErrorCode, ErrorDetail, ErrorStatus, ValidationIssue }
|
|
|
49
67
|
export { createIdFactory, idPrefixes } from './lib/ids.ts'
|
|
50
68
|
export type { IdFactory, ObjectKind } from './lib/ids.ts'
|
|
51
69
|
|
|
52
|
-
export {
|
|
53
|
-
|
|
70
|
+
export {
|
|
71
|
+
createCaptureTransport,
|
|
72
|
+
createLogger,
|
|
73
|
+
createStdoutTransport,
|
|
74
|
+
createTransportForDestination,
|
|
75
|
+
} from './lib/logger.ts'
|
|
76
|
+
export type { CreateLoggerOptions, LogFields, Logger, LoggingDestination } from './lib/logger.ts'
|
|
54
77
|
|
|
55
78
|
export type {
|
|
56
79
|
KelpieModule,
|
|
@@ -76,21 +99,33 @@ export type {
|
|
|
76
99
|
|
|
77
100
|
export { SEATS_LIMIT } from './modules/workspace/capabilities.ts'
|
|
78
101
|
|
|
79
|
-
export {
|
|
102
|
+
export {
|
|
103
|
+
RECORD_OBJECT_TYPES,
|
|
104
|
+
checkEventCycle,
|
|
105
|
+
createEventBus,
|
|
106
|
+
currentEventChain,
|
|
107
|
+
} from './runtime/events.ts'
|
|
80
108
|
export type {
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
AnyEventHandler,
|
|
110
|
+
CycleGuardOutcome,
|
|
83
111
|
EventBus,
|
|
112
|
+
EventBusOptions,
|
|
113
|
+
EventCatalog,
|
|
114
|
+
EventChainEntry,
|
|
84
115
|
EventHandler,
|
|
116
|
+
EventName,
|
|
117
|
+
KelpieEventMap,
|
|
85
118
|
RecordObjectType,
|
|
86
|
-
|
|
119
|
+
SubscribeOptions,
|
|
87
120
|
} from './runtime/events.ts'
|
|
121
|
+
export type { ModuleEventCatalog } from './runtime/module.ts'
|
|
88
122
|
|
|
89
123
|
export { createTransactionScope } from './runtime/transaction.ts'
|
|
90
124
|
export type {
|
|
91
125
|
BufferedEvents,
|
|
92
126
|
Transaction,
|
|
93
127
|
TransactionContext,
|
|
128
|
+
TransactionOptions,
|
|
94
129
|
TransactionScope,
|
|
95
130
|
TransactionScopeDependencies,
|
|
96
131
|
} from './runtime/transaction.ts'
|
|
@@ -100,8 +135,8 @@ export type { MigrationPlanStep } from './runtime/migrate.ts'
|
|
|
100
135
|
|
|
101
136
|
export { coreMigrationsDirectory, coreModules } from './modules/core.ts'
|
|
102
137
|
|
|
103
|
-
export { resealStoredSecrets } from './modules/reseal.ts'
|
|
104
|
-
export type { ResealColumnOutcome, ResealOutcome } from './modules/reseal.ts'
|
|
138
|
+
export { resealStoredSecrets, runReseal } from './modules/reseal.ts'
|
|
139
|
+
export type { ResealColumnOutcome, ResealOutcome, ResealPass, RunResealOptions } from './modules/reseal.ts'
|
|
105
140
|
|
|
106
141
|
export { KEY_KINDS, kindOfSecret, mintKey, parseKeyKind, readBearerToken } from './modules/api-keys/keys.ts'
|
|
107
142
|
export type { KeyKind, MintedKey } from './modules/api-keys/keys.ts'
|
package/src/lib/actor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MemberRole } from '@kelpie/schemas'
|
|
1
|
+
import type { EventActor, MemberRole } from '@kelpie/schemas'
|
|
2
2
|
|
|
3
3
|
import { AppError } from './errors.ts'
|
|
4
4
|
|
|
@@ -97,3 +97,17 @@ export function actorUserId(actor: Actor): string | null {
|
|
|
97
97
|
export function actorMemberId(actor: Actor): string | null {
|
|
98
98
|
return actor.memberId
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Maps the request actor to the actor stamped on domain events.
|
|
103
|
+
*
|
|
104
|
+
* A signed-in user becomes `user`. A workspace key (no user behind it) becomes
|
|
105
|
+
* `system`, because the event was caused by the workspace itself rather than
|
|
106
|
+
* any one person.
|
|
107
|
+
*/
|
|
108
|
+
export function toEventActor(actor: Actor): EventActor {
|
|
109
|
+
if (actor.userId !== null) {
|
|
110
|
+
return { kind: 'user', id: actor.userId }
|
|
111
|
+
}
|
|
112
|
+
return { kind: 'system' }
|
|
113
|
+
}
|
package/src/lib/config.ts
CHANGED
|
@@ -3,8 +3,14 @@ import { z } from 'zod'
|
|
|
3
3
|
import { emailConfigSchema } from './email.ts'
|
|
4
4
|
import type { EmailConfig } from './email.ts'
|
|
5
5
|
import { describeValidationIssue } from './errors.ts'
|
|
6
|
+
// `EmailConfig` is `{ EMAIL_PROVIDER, EMAIL_FROM }`. `EMAIL_PROVIDER` names one
|
|
7
|
+
// of the registered senders; `'log'` is always available, other names come
|
|
8
|
+
// from provider modules. Provider-specific config (SMTP settings, an API key)
|
|
9
|
+
// belongs to the module that reads it through `context.config(...)`.
|
|
10
|
+
import type { LoggingDestination } from './logger.ts'
|
|
6
11
|
import { rateLimitConfigFrom, rateLimitConfigSchema } from './rateLimit.ts'
|
|
7
12
|
import type { RateLimitConfig } from './rateLimit.ts'
|
|
13
|
+
import type { SecretEncryptionConfig } from './secrets.ts'
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
16
|
* The single place the service reads environment variables. Every other module
|
|
@@ -18,12 +24,29 @@ export type RuntimeMode = 'development' | 'test' | 'production'
|
|
|
18
24
|
|
|
19
25
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
|
20
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Everything the logger needs to boot: the minimum severity to emit, and the
|
|
29
|
+
* ordered list of destinations each line is written to. Stdout is one such
|
|
30
|
+
* destination; adding a file or a hosted collector means adding an entry to
|
|
31
|
+
* `destinations` and extending `LoggingDestination` in `lib/logger.ts`.
|
|
32
|
+
*/
|
|
33
|
+
export interface LoggingConfig {
|
|
34
|
+
readonly level: LogLevel
|
|
35
|
+
readonly destinations: readonly LoggingDestination[]
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
export interface KelpieConfig {
|
|
22
39
|
readonly runtimeMode: RuntimeMode
|
|
23
40
|
readonly port: number
|
|
24
41
|
readonly databaseUrl: string
|
|
25
|
-
readonly
|
|
26
|
-
/**
|
|
42
|
+
readonly logging: LoggingConfig
|
|
43
|
+
/**
|
|
44
|
+
* The provider name the module runtime looks up in its registry, and the
|
|
45
|
+
* from address every outgoing message uses. See `lib/email.ts` for the
|
|
46
|
+
* shape and rules; `'log'` is always available, `'smtp'` is registered by
|
|
47
|
+
* the built-in `smtp-email` core module, and other names come from
|
|
48
|
+
* third-party provider modules.
|
|
49
|
+
*/
|
|
27
50
|
readonly email: EmailConfig
|
|
28
51
|
/**
|
|
29
52
|
* Path to the deploy-time module override file (`lib/moduleConfig.ts`).
|
|
@@ -44,6 +67,28 @@ export interface KelpieConfig {
|
|
|
44
67
|
* client IP is read from `X-Forwarded-For` (`lib/clientIp.ts`).
|
|
45
68
|
*/
|
|
46
69
|
readonly trustedProxyHopCount: number
|
|
70
|
+
/**
|
|
71
|
+
* What modules see through `context.config(schema)`. `resolveKelpieConfig`
|
|
72
|
+
* produces this by merging any `env` section in `kelpie.config.ts` over
|
|
73
|
+
* `process.env`, so a key in the config file wins for that key and unset
|
|
74
|
+
* keys pass through. `loadConfig` sets it to the environment it was given,
|
|
75
|
+
* so an old caller keeps the same behaviour.
|
|
76
|
+
*/
|
|
77
|
+
readonly env: Environment
|
|
78
|
+
/**
|
|
79
|
+
* The deployment's base URL, source of every emailed link. Optional so an
|
|
80
|
+
* older assembly that omits it from `kelpie.config.ts` still boots: modules
|
|
81
|
+
* that need it fall back to `context.config(appUrlConfigSchema)` when unset.
|
|
82
|
+
* A new assembly declares it as a first-class field.
|
|
83
|
+
*/
|
|
84
|
+
readonly appBaseUrl: string | undefined
|
|
85
|
+
/**
|
|
86
|
+
* The key(s) that seal stored secrets. Optional for the same reason
|
|
87
|
+
* `appBaseUrl` is: modules that need it fall back to
|
|
88
|
+
* `context.config(secretEncryptionConfigSchema)`. The base assembly declares
|
|
89
|
+
* it, so both webhooks and agent-tasks receive it through `services`.
|
|
90
|
+
*/
|
|
91
|
+
readonly secretEncryption: SecretEncryptionConfig | undefined
|
|
47
92
|
}
|
|
48
93
|
|
|
49
94
|
/** Thrown at boot when the environment cannot produce a valid configuration. */
|
|
@@ -82,10 +127,8 @@ const environmentSchema = z.object({
|
|
|
82
127
|
/**
|
|
83
128
|
* Parses an environment into a validated config.
|
|
84
129
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* only its own `EMAIL_PROVIDER`-keyed branches. Problems from both parses are
|
|
88
|
-
* combined into one error, preserving the "every missing variable at once" rule.
|
|
130
|
+
* The email variables are parsed separately so a caller sees every missing
|
|
131
|
+
* variable at once, rather than one at a time.
|
|
89
132
|
*
|
|
90
133
|
* @param environment Raw variables, normally `process.env`.
|
|
91
134
|
* @throws ConfigurationError listing every invalid or missing variable.
|
|
@@ -107,11 +150,17 @@ export function loadConfig(environment: Environment): KelpieConfig {
|
|
|
107
150
|
runtimeMode: environmentResult.data.NODE_ENV,
|
|
108
151
|
port: environmentResult.data.PORT,
|
|
109
152
|
databaseUrl: environmentResult.data.DATABASE_URL,
|
|
110
|
-
|
|
153
|
+
logging: {
|
|
154
|
+
level: environmentResult.data.LOG_LEVEL,
|
|
155
|
+
destinations: [{ kind: 'stdout' }],
|
|
156
|
+
},
|
|
111
157
|
email: emailResult.data,
|
|
112
158
|
moduleConfigPath: environmentResult.data.KELPIE_MODULE_CONFIG_PATH,
|
|
113
159
|
webBundleDirectory: environmentResult.data.WEB_BUNDLE_DIR,
|
|
114
160
|
rateLimit: rateLimitConfigFrom(environmentResult.data),
|
|
115
161
|
trustedProxyHopCount: environmentResult.data.TRUSTED_PROXY_HOP_COUNT,
|
|
162
|
+
env: environment,
|
|
163
|
+
appBaseUrl: undefined,
|
|
164
|
+
secretEncryption: undefined,
|
|
116
165
|
}
|
|
117
166
|
}
|
package/src/lib/email.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import nodemailer from 'nodemailer'
|
|
2
1
|
import { z } from 'zod'
|
|
3
2
|
|
|
4
|
-
import { describeThrown } from './errors.ts'
|
|
5
3
|
import type { Logger } from './logger.ts'
|
|
6
4
|
|
|
7
5
|
/**
|
|
@@ -9,15 +7,15 @@ import type { Logger } from './logger.ts'
|
|
|
9
7
|
* and account-change notifications, nothing else. Kelpie never sends outreach
|
|
10
8
|
* email.
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* a
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
10
|
+
* The assembly names one named provider in `kelpie.config.ts`'s
|
|
11
|
+
* `email.provider`. The module runtime resolves the name against a registry
|
|
12
|
+
* every module can contribute to via `context.provideEmailSender(name, sender)`.
|
|
13
|
+
* `'log'` is a built-in name the runtime always registers, so a bare install
|
|
14
|
+
* has something to point at. `'smtp'` is registered by the built-in
|
|
15
|
+
* `smtp-email` core module. Other names come from third-party provider modules
|
|
16
|
+
* (Resend, Postmark, SES) that follow the same registry pattern. Transport is
|
|
17
|
+
* arbitrary: the module builds one behind the `EmailSender` interface and
|
|
18
|
+
* hands it to core, which knows only how to `send`.
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
21
|
export interface EmailMessage {
|
|
@@ -30,40 +28,29 @@ export interface EmailSender {
|
|
|
30
28
|
send(message: EmailMessage): Promise<void>
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
const
|
|
34
|
-
|
|
31
|
+
export const emailConfigSchema = z.object({
|
|
32
|
+
/**
|
|
33
|
+
* The named provider `registerModules` resolves against its registry. `'log'`
|
|
34
|
+
* is a built-in, always present. Any other name needs a module that
|
|
35
|
+
* registered it via `context.provideEmailSender(name, sender)`. Free-string
|
|
36
|
+
* so a self-hoster can add a module core has never heard of.
|
|
37
|
+
*/
|
|
38
|
+
EMAIL_PROVIDER: z.string().min(1),
|
|
35
39
|
EMAIL_FROM: z.string().min(1),
|
|
36
40
|
})
|
|
37
41
|
|
|
38
|
-
const smtpEmailConfigSchema = z.object({
|
|
39
|
-
EMAIL_PROVIDER: z.literal('smtp'),
|
|
40
|
-
EMAIL_FROM: z.string().min(1),
|
|
41
|
-
SMTP_HOST: z.string().min(1),
|
|
42
|
-
SMTP_PORT: z.coerce.number().int().positive().max(65535),
|
|
43
|
-
SMTP_SECURE: z.enum(['true', 'false']).transform((value) => value === 'true'),
|
|
44
|
-
SMTP_USER: z.string().min(1),
|
|
45
|
-
SMTP_PASSWORD: z.string().min(1),
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
export const emailConfigSchema = z.discriminatedUnion('EMAIL_PROVIDER', [
|
|
49
|
-
logEmailConfigSchema,
|
|
50
|
-
smtpEmailConfigSchema,
|
|
51
|
-
])
|
|
52
|
-
|
|
53
42
|
export type EmailConfig = z.infer<typeof emailConfigSchema>
|
|
54
|
-
export type SmtpEmailConfig = z.infer<typeof smtpEmailConfigSchema>
|
|
55
43
|
|
|
56
44
|
/**
|
|
57
|
-
* Writes the message to the log instead of sending it.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* so nobody reaches this provider without naming it.
|
|
45
|
+
* Writes the message to the log instead of sending it. The registry default,
|
|
46
|
+
* swapped out for a real sender by picking a different provider name in
|
|
47
|
+
* `email.provider` (`'smtp'` for the built-in SMTP module, or any name a
|
|
48
|
+
* third-party provider module registers).
|
|
62
49
|
*/
|
|
63
50
|
export function createLogEmailSender(logger: Logger, from: string): EmailSender {
|
|
64
51
|
return {
|
|
65
52
|
send(message) {
|
|
66
|
-
logger.info('email not sent: provider
|
|
53
|
+
logger.info('email not sent: no provider module registered', {
|
|
67
54
|
from,
|
|
68
55
|
to: message.to,
|
|
69
56
|
subject: message.subject,
|
|
@@ -74,60 +61,3 @@ export function createLogEmailSender(logger: Logger, from: string): EmailSender
|
|
|
74
61
|
},
|
|
75
62
|
}
|
|
76
63
|
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* What `createSmtpEmailSender` sends a message through. A real deployment gets
|
|
80
|
-
* one backed by `nodemailer`; a test injects one that records calls, so the
|
|
81
|
-
* sender is verifiable without a container running a real SMTP conversation.
|
|
82
|
-
*/
|
|
83
|
-
export interface SmtpTransport {
|
|
84
|
-
sendMail(message: { from: string; to: string; subject: string; text: string }): Promise<unknown>
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function createNodemailerTransport(config: SmtpEmailConfig): SmtpTransport {
|
|
88
|
-
return nodemailer.createTransport({
|
|
89
|
-
host: config.SMTP_HOST,
|
|
90
|
-
port: config.SMTP_PORT,
|
|
91
|
-
secure: config.SMTP_SECURE,
|
|
92
|
-
auth: { user: config.SMTP_USER, pass: config.SMTP_PASSWORD },
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** Sends over SMTP. `transport` defaults to a real connection built from `config`. */
|
|
97
|
-
export function createSmtpEmailSender(
|
|
98
|
-
config: SmtpEmailConfig,
|
|
99
|
-
logger: Logger,
|
|
100
|
-
transport: SmtpTransport = createNodemailerTransport(config),
|
|
101
|
-
): EmailSender {
|
|
102
|
-
return {
|
|
103
|
-
async send(message) {
|
|
104
|
-
try {
|
|
105
|
-
await transport.sendMail({
|
|
106
|
-
from: config.EMAIL_FROM,
|
|
107
|
-
to: message.to,
|
|
108
|
-
subject: message.subject,
|
|
109
|
-
text: message.body,
|
|
110
|
-
})
|
|
111
|
-
} catch (cause) {
|
|
112
|
-
const reason = describeThrown(cause)
|
|
113
|
-
logger.error('smtp send failed', { to: message.to, reason })
|
|
114
|
-
throw new Error(`Failed to send email to ${message.to} over SMTP: ${reason}`, { cause })
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Builds the configured sender.
|
|
122
|
-
*
|
|
123
|
-
* @throws Never. An unknown provider cannot reach here: the config schema is a
|
|
124
|
-
* discriminated union, so boot rejects it first.
|
|
125
|
-
*/
|
|
126
|
-
export function createEmailSender(config: EmailConfig, logger: Logger): EmailSender {
|
|
127
|
-
switch (config.EMAIL_PROVIDER) {
|
|
128
|
-
case 'log':
|
|
129
|
-
return createLogEmailSender(logger, config.EMAIL_FROM)
|
|
130
|
-
case 'smtp':
|
|
131
|
-
return createSmtpEmailSender(config, logger)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ZodType } from 'zod'
|
|
2
|
+
|
|
3
|
+
import type { Environment } from './config.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A marker a `kelpie.config.ts` file uses to say "read this leaf from the
|
|
7
|
+
* environment." The assembly's config file is the shape and the defaults;
|
|
8
|
+
* `fromEnv` marks the leaves a deployment may override without a code change.
|
|
9
|
+
*
|
|
10
|
+
* Every marker names an env var, the Zod schema that parses it, and optionally
|
|
11
|
+
* a default. Without a default the marker is required: the env var must be set,
|
|
12
|
+
* or boot fails with the other configuration problems.
|
|
13
|
+
*
|
|
14
|
+
* The resolver walks the config object, replaces each marker with the parsed
|
|
15
|
+
* value, and returns the fully-resolved object. Nothing in the app reads
|
|
16
|
+
* `process.env` for these fields after boot.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const FROM_ENV_MARKER = Symbol.for('kelpie.fromEnv')
|
|
20
|
+
|
|
21
|
+
export interface FromEnvMarker<T> {
|
|
22
|
+
readonly [FROM_ENV_MARKER]: true
|
|
23
|
+
readonly envKey: string
|
|
24
|
+
readonly schema: ZodType<T>
|
|
25
|
+
readonly defaultValue: T | undefined
|
|
26
|
+
readonly hasDefault: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A leaf in the config file: either a literal already-typed value, or a marker. */
|
|
30
|
+
export type ConfigValue<T> = T | FromEnvMarker<T>
|
|
31
|
+
|
|
32
|
+
export function fromEnv<T>(envKey: string, schema: ZodType<T>): FromEnvMarker<T>
|
|
33
|
+
export function fromEnv<T>(envKey: string, schema: ZodType<T>, defaultValue: T): FromEnvMarker<T>
|
|
34
|
+
export function fromEnv<T>(envKey: string, schema: ZodType<T>, defaultValue?: T): FromEnvMarker<T> {
|
|
35
|
+
const hasDefault = arguments.length >= 3
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
[FROM_ENV_MARKER]: true,
|
|
39
|
+
envKey,
|
|
40
|
+
schema,
|
|
41
|
+
defaultValue: hasDefault ? (defaultValue as T) : undefined,
|
|
42
|
+
hasDefault,
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isFromEnvMarker(value: unknown): value is FromEnvMarker<unknown> {
|
|
47
|
+
return typeof value === 'object' && value !== null && (value as Record<PropertyKey, unknown>)[FROM_ENV_MARKER] === true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** One problem discovered while resolving markers. Path is the dotted field. */
|
|
51
|
+
export interface FromEnvProblem {
|
|
52
|
+
readonly path: string
|
|
53
|
+
readonly message: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ResolveResult<T> {
|
|
57
|
+
readonly value: T | undefined
|
|
58
|
+
readonly problems: readonly FromEnvProblem[]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolves one marker against an environment.
|
|
63
|
+
*
|
|
64
|
+
* Missing and no default: one required problem.
|
|
65
|
+
* Missing with default: the default, unvalidated. A hardcoded default is
|
|
66
|
+
* trusted because the developer wrote it in the assembly file.
|
|
67
|
+
* Present: parsed through the marker's schema. Parse failures become problems.
|
|
68
|
+
*/
|
|
69
|
+
export function resolveMarker<T>(marker: FromEnvMarker<T>, environment: Environment, path: string): ResolveResult<T> {
|
|
70
|
+
const raw = environment[marker.envKey]
|
|
71
|
+
|
|
72
|
+
if (raw === undefined) {
|
|
73
|
+
if (marker.hasDefault) {
|
|
74
|
+
return { value: marker.defaultValue, problems: [] }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
value: undefined,
|
|
79
|
+
problems: [{ path, message: `${marker.envKey} is required` }],
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const result = marker.schema.safeParse(raw)
|
|
84
|
+
|
|
85
|
+
if (!result.success) {
|
|
86
|
+
return {
|
|
87
|
+
value: undefined,
|
|
88
|
+
problems: result.error.issues.map((issue) => ({
|
|
89
|
+
path,
|
|
90
|
+
message: `${marker.envKey}: ${issue.message}`,
|
|
91
|
+
})),
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { value: result.data, problems: [] }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Walks any value, replacing every `FromEnvMarker` with its resolved value.
|
|
100
|
+
* Objects and arrays are walked recursively; other values pass through.
|
|
101
|
+
*
|
|
102
|
+
* Collects problems from every marker rather than throwing at the first one,
|
|
103
|
+
* so a self-hoster fixes their environment once rather than a variable at a
|
|
104
|
+
* time.
|
|
105
|
+
*/
|
|
106
|
+
export function resolveMarkers(
|
|
107
|
+
input: unknown,
|
|
108
|
+
environment: Environment,
|
|
109
|
+
path = '',
|
|
110
|
+
): { readonly value: unknown; readonly problems: readonly FromEnvProblem[] } {
|
|
111
|
+
if (isFromEnvMarker(input)) {
|
|
112
|
+
return resolveMarker(input, environment, path)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (Array.isArray(input)) {
|
|
116
|
+
const problems: FromEnvProblem[] = []
|
|
117
|
+
const value = input.map((item, index) => {
|
|
118
|
+
const childPath = `${path}[${String(index)}]`
|
|
119
|
+
const result = resolveMarkers(item, environment, childPath)
|
|
120
|
+
problems.push(...result.problems)
|
|
121
|
+
|
|
122
|
+
return result.value
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return { value, problems }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof input === 'object' && input !== null) {
|
|
129
|
+
const problems: FromEnvProblem[] = []
|
|
130
|
+
const value: Record<string, unknown> = {}
|
|
131
|
+
|
|
132
|
+
for (const [key, child] of Object.entries(input)) {
|
|
133
|
+
const childPath = path.length > 0 ? `${path}.${key}` : key
|
|
134
|
+
const result = resolveMarkers(child, environment, childPath)
|
|
135
|
+
problems.push(...result.problems)
|
|
136
|
+
value[key] = result.value
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { value, problems }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return { value: input, problems: [] }
|
|
143
|
+
}
|
package/src/lib/ids.ts
CHANGED
|
@@ -52,6 +52,12 @@ export const idPrefixes = {
|
|
|
52
52
|
* a bucket is bookkeeping the rate limiter owns, not a resource with routes.
|
|
53
53
|
*/
|
|
54
54
|
rateLimitBucket: 'rl',
|
|
55
|
+
/**
|
|
56
|
+
* One published domain event. Stamped on the envelope so downstream consumers
|
|
57
|
+
* (webhooks, MCP subscribers, an eventual outbox) have a stable idempotency
|
|
58
|
+
* key. Not persisted by core.
|
|
59
|
+
*/
|
|
60
|
+
event: 'ev',
|
|
55
61
|
} as const
|
|
56
62
|
|
|
57
63
|
export type ObjectKind = keyof typeof idPrefixes
|