@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7
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/.turbo/turbo-build.log +4 -4
- package/build.mjs +7 -24
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
- package/dist/agentic/codex/enforcement-rules.md +16 -2
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
- package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
- package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
- package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
- package/dist/agentic/guides/cache.md +45 -0
- package/dist/agentic/guides/core.md +453 -0
- package/dist/agentic/guides/events.md +117 -0
- package/dist/agentic/guides/module-facts.json +3833 -115419
- package/dist/agentic/guides/module-system.md +127 -12
- package/dist/agentic/guides/modules/ai_assistant.md +28 -227
- package/dist/agentic/guides/modules/api_docs.md +2 -58
- package/dist/agentic/guides/modules/api_keys.md +7 -92
- package/dist/agentic/guides/modules/attachments.md +14 -119
- package/dist/agentic/guides/modules/audit_logs.md +10 -131
- package/dist/agentic/guides/modules/auth.md +33 -276
- package/dist/agentic/guides/modules/business_rules.md +14 -149
- package/dist/agentic/guides/modules/catalog.md +43 -475
- package/dist/agentic/guides/modules/channel_gmail.md +3 -82
- package/dist/agentic/guides/modules/channel_imap.md +3 -82
- package/dist/agentic/guides/modules/checkout.md +27 -299
- package/dist/agentic/guides/modules/communication_channels.md +33 -315
- package/dist/agentic/guides/modules/configs.md +8 -104
- package/dist/agentic/guides/modules/content.md +2 -57
- package/dist/agentic/guides/modules/currencies.md +17 -152
- package/dist/agentic/guides/modules/customer_accounts.md +45 -387
- package/dist/agentic/guides/modules/customers.md +85 -746
- package/dist/agentic/guides/modules/dashboards.md +10 -155
- package/dist/agentic/guides/modules/data_sync.md +16 -149
- package/dist/agentic/guides/modules/dictionaries.md +12 -107
- package/dist/agentic/guides/modules/directory.md +15 -148
- package/dist/agentic/guides/modules/entities.md +13 -145
- package/dist/agentic/guides/modules/events.md +2 -59
- package/dist/agentic/guides/modules/feature_toggles.md +9 -119
- package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
- package/dist/agentic/guides/modules/generators.md +2 -45
- package/dist/agentic/guides/modules/inbox_ops.md +27 -207
- package/dist/agentic/guides/modules/integrations.md +16 -146
- package/dist/agentic/guides/modules/messages.md +24 -223
- package/dist/agentic/guides/modules/notifications.md +8 -96
- package/dist/agentic/guides/modules/onboarding.md +6 -77
- package/dist/agentic/guides/modules/payment_gateways.md +21 -164
- package/dist/agentic/guides/modules/perspectives.md +7 -77
- package/dist/agentic/guides/modules/planner.md +18 -136
- package/dist/agentic/guides/modules/portal.md +2 -93
- package/dist/agentic/guides/modules/progress.md +14 -104
- package/dist/agentic/guides/modules/query_index.md +15 -154
- package/dist/agentic/guides/modules/record_locks.md +21 -206
- package/dist/agentic/guides/modules/resources.md +30 -197
- package/dist/agentic/guides/modules/sales.md +84 -678
- package/dist/agentic/guides/modules/scheduler.md +14 -133
- package/dist/agentic/guides/modules/search.md +6 -170
- package/dist/agentic/guides/modules/security.md +35 -294
- package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
- package/dist/agentic/guides/modules/sso.md +26 -151
- package/dist/agentic/guides/modules/staff.md +57 -369
- package/dist/agentic/guides/modules/storage_s3.md +5 -95
- package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
- package/dist/agentic/guides/modules/sync_excel.md +6 -75
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
- package/dist/agentic/guides/modules/translations.md +10 -104
- package/dist/agentic/guides/modules/webhooks.md +24 -203
- package/dist/agentic/guides/modules/wms.md +46 -441
- package/dist/agentic/guides/modules/workflows.md +43 -302
- package/dist/agentic/guides/queue.md +53 -0
- package/dist/agentic/guides/search.md +115 -0
- package/dist/agentic/guides/shared.md +108 -0
- package/dist/agentic/guides/ui.md +347 -0
- package/dist/agentic/shared/AGENTS.md.template +311 -124
- package/dist/agentic/shared/ai/agentic.config.json +0 -2
- package/dist/agentic/shared/ai/lessons.md +3 -26
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
- package/dist/agentic/shared/ai/skills/tiers.json +21 -143
- package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
- package/dist/agentic/shared/ai/specs/README.md +3 -4
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
- package/dist/agentic/shared/ai/trackers/github.md +4 -108
- package/dist/agentic/shared/scripts/install-skills.sh +694 -4
- package/dist/bin.js +1 -13
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +3 -13
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +186 -418
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +0 -20
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-facts-discovery.js +7 -41
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +45 -1387
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-registry.js +5 -11
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +0 -2
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -5
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +1 -23
- package/dist/mercato.js.map +2 -2
- package/package.json +11 -13
- package/src/bin.ts +1 -33
- package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
- package/src/lib/__tests__/agentic-init.test.ts +5 -41
- package/src/lib/agentic-init.ts +3 -15
- package/src/lib/agentic-setup.ts +224 -530
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
- package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
- package/src/lib/generators/extensions/injection-widgets.ts +0 -51
- package/src/lib/generators/module-facts-discovery.ts +7 -58
- package/src/lib/generators/module-facts.ts +46 -1851
- package/src/lib/generators/module-registry.ts +6 -16
- package/src/lib/resolver.ts +0 -3
- package/src/lib/testing/__tests__/integration.test.ts +0 -4
- package/src/lib/testing/integration.ts +0 -5
- package/src/mercato.ts +1 -26
- package/dist/agentic/guides/ai-workflows.md +0 -76
- package/dist/agentic/guides/architecture.md +0 -107
- package/dist/agentic/guides/backend-ui.md +0 -80
- package/dist/agentic/guides/contracts.md +0 -92
- package/dist/agentic/guides/extensions.md +0 -121
- package/dist/agentic/guides/framework-extension-points.md +0 -36
- package/dist/agentic/guides/integrations.md +0 -81
- package/dist/agentic/guides/modules/design_system.md +0 -102
- package/dist/agentic/guides/spec-delivery.md +0 -22
- package/dist/agentic/guides/testing-debugging.md +0 -80
- package/dist/agentic/guides/upstream/AGENTS.md +0 -298
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
- package/dist/agentic/guides/upstream/manifest.json +0 -8
- package/dist/agentic/shared/ai/harness/README.md +0 -50
- package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
- package/dist/agentic/shared/ai/harness/cases.json +0 -13680
- package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
- package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
- package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
- package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
- package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
- package/dist/agentic/shared/ai/harness/validators.json +0 -78
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
- package/dist/agentic/shared/ai/lessons/_template.md +0 -16
- package/dist/agentic/shared/ai/review-checklist.md +0 -36
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
- package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
- package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
- package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
- package/dist/lib/generators/module-extension-facts.js +0 -1840
- package/dist/lib/generators/module-extension-facts.js.map +0 -7
- package/dist/lib/generators/module-fact-sources.js +0 -70
- package/dist/lib/generators/module-fact-sources.js.map +0 -7
- package/dist/lib/generators/module-override-targets.js +0 -688
- package/dist/lib/generators/module-override-targets.js.map +0 -7
- package/dist/lib/load-env.js +0 -24
- package/dist/lib/load-env.js.map +0 -7
- package/dist/lib/telemetry-init.js +0 -358
- package/dist/lib/telemetry-init.js.map +0 -7
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
- package/src/lib/__tests__/load-env.test.ts +0 -65
- package/src/lib/__tests__/telemetry-init.test.ts +0 -298
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
- package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
- package/src/lib/generators/module-extension-facts.ts +0 -2365
- package/src/lib/generators/module-fact-sources.ts +0 -108
- package/src/lib/generators/module-override-targets.ts +0 -863
- package/src/lib/load-env.ts +0 -30
- package/src/lib/telemetry-init.ts +0 -461
|
@@ -224,8 +224,6 @@ type SerializableWorkerMetadata = {
|
|
|
224
224
|
id?: string
|
|
225
225
|
queue?: string
|
|
226
226
|
concurrency?: number
|
|
227
|
-
lockDuration?: number
|
|
228
|
-
maxStalledCount?: number
|
|
229
227
|
}
|
|
230
228
|
|
|
231
229
|
type PageMetadataManifestLoadResult = {
|
|
@@ -1157,7 +1155,7 @@ function collectStringArrayElements(expr: ts.Expression, stringConstants: Map<st
|
|
|
1157
1155
|
return values
|
|
1158
1156
|
}
|
|
1159
1157
|
|
|
1160
|
-
|
|
1158
|
+
function extractCommandIdsFromSource(sourcePath: string): string[] {
|
|
1161
1159
|
const sourceText = fs.readFileSync(sourcePath, 'utf8')
|
|
1162
1160
|
const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
|
|
1163
1161
|
const ids = new Set<string>()
|
|
@@ -1555,8 +1553,6 @@ function normalizeWorkerMetadata(raw: unknown): SerializableWorkerMetadata | nul
|
|
|
1555
1553
|
if (typeof source.id === 'string' && source.id.length > 0) normalized.id = source.id
|
|
1556
1554
|
if (typeof source.queue === 'string' && source.queue.length > 0) normalized.queue = source.queue
|
|
1557
1555
|
if (typeof source.concurrency === 'number') normalized.concurrency = source.concurrency
|
|
1558
|
-
if (typeof source.lockDuration === 'number') normalized.lockDuration = source.lockDuration
|
|
1559
|
-
if (typeof source.maxStalledCount === 'number') normalized.maxStalledCount = source.maxStalledCount
|
|
1560
1556
|
return Object.keys(normalized).length > 0 ? normalized : null
|
|
1561
1557
|
}
|
|
1562
1558
|
|
|
@@ -2059,7 +2055,7 @@ function processWorkers(discovered: DiscoveredWorker[]): string[] {
|
|
|
2059
2055
|
for (const { id, importPath, metadata } of discovered) {
|
|
2060
2056
|
const workerId = metadata.id ?? id
|
|
2061
2057
|
workers.push(
|
|
2062
|
-
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}
|
|
2058
|
+
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
2063
2059
|
)
|
|
2064
2060
|
}
|
|
2065
2061
|
return workers
|
|
@@ -2734,8 +2730,6 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
|
|
|
2734
2730
|
{ name: 'id', value: workerId },
|
|
2735
2731
|
{ name: 'queue', value: metadata.queue },
|
|
2736
2732
|
{ name: 'concurrency', value: metadata.concurrency ?? 1 },
|
|
2737
|
-
...(metadata.lockDuration === undefined ? [] : [{ name: 'lockDuration', value: metadata.lockDuration }]),
|
|
2738
|
-
...(metadata.maxStalledCount === undefined ? [] : [{ name: 'maxStalledCount', value: metadata.maxStalledCount }]),
|
|
2739
2733
|
{
|
|
2740
2734
|
name: 'handler',
|
|
2741
2735
|
value: callExpression(identifier('createLazyModuleWorker'), [
|
|
@@ -3065,10 +3059,6 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3065
3059
|
if (fields) fieldsImportName = fields.importName
|
|
3066
3060
|
}
|
|
3067
3061
|
|
|
3068
|
-
const integrationExports = integrationImportName
|
|
3069
|
-
? `(${integrationImportName} as unknown as { integrations?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]; integration?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition; bundles?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]; bundle?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle })`
|
|
3070
|
-
: null
|
|
3071
|
-
|
|
3072
3062
|
// 13. Pages: backend
|
|
3073
3063
|
{
|
|
3074
3064
|
const beApp = path.join(roots.appBase, 'backend')
|
|
@@ -3177,8 +3167,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3177
3167
|
${dashboardWidgets.length ? `dashboardWidgets: [${dashboardWidgets.join(', ')}],` : ''}
|
|
3178
3168
|
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3179
3169
|
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3180
|
-
${
|
|
3181
|
-
${
|
|
3170
|
+
${integrationImportName ? `integrations: (( ${integrationImportName}.integrations ?? (${integrationImportName}.integration ? [${integrationImportName}.integration] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3171
|
+
${integrationImportName ? `bundles: (( ${integrationImportName}.bundles ?? (${integrationImportName}.bundle ? [${integrationImportName}.bundle] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3182
3172
|
}`)
|
|
3183
3173
|
runtimeModuleDecls.push(`{
|
|
3184
3174
|
id: ${toLiteral(modId)},
|
|
@@ -3195,8 +3185,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3195
3185
|
${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ''}
|
|
3196
3186
|
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3197
3187
|
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3198
|
-
${
|
|
3199
|
-
${
|
|
3188
|
+
${integrationImportName ? `integrations: (( ${integrationImportName}.integrations ?? (${integrationImportName}.integration ? [${integrationImportName}.integration] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3189
|
+
${integrationImportName ? `bundles: (( ${integrationImportName}.bundles ?? (${integrationImportName}.bundle ? [${integrationImportName}.bundle] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3200
3190
|
}`)
|
|
3201
3191
|
}
|
|
3202
3192
|
|
package/src/lib/resolver.ts
CHANGED
|
@@ -29,7 +29,6 @@ export type ModuleEntry = {
|
|
|
29
29
|
|
|
30
30
|
export type PackageInfo = {
|
|
31
31
|
name: string
|
|
32
|
-
version?: string | null
|
|
33
32
|
path: string
|
|
34
33
|
modulesPath: string
|
|
35
34
|
}
|
|
@@ -357,7 +356,6 @@ function discoverPackagesInMonorepo(rootDir: string): PackageInfo[] {
|
|
|
357
356
|
if (fs.existsSync(modulesPath)) {
|
|
358
357
|
packages.push({
|
|
359
358
|
name: pkgJson.name || `@open-mercato/${entry.name}`,
|
|
360
|
-
version: typeof pkgJson.version === 'string' ? pkgJson.version : null,
|
|
361
359
|
path: pkgPath,
|
|
362
360
|
modulesPath,
|
|
363
361
|
})
|
|
@@ -393,7 +391,6 @@ function discoverPackagesInNodeModules(rootDir: string): PackageInfo[] {
|
|
|
393
391
|
if (fs.existsSync(modulesPath)) {
|
|
394
392
|
packages.push({
|
|
395
393
|
name: pkgJson.name || `@open-mercato/${entry.name}`,
|
|
396
|
-
version: typeof pkgJson.version === 'string' ? pkgJson.version : null,
|
|
397
394
|
path: pkgPath,
|
|
398
395
|
modulesPath,
|
|
399
396
|
})
|
|
@@ -186,10 +186,6 @@ describe('integration cache and options', () => {
|
|
|
186
186
|
expect(environment?.commandEnvironment.QUEUE_BASE_DIR).toBe('/tmp/open-mercato-queue')
|
|
187
187
|
expect(environment?.commandEnvironment[PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY]).toBe(defaultPrivateAttachmentsRoot)
|
|
188
188
|
expect(environment?.commandEnvironment.PW_CAPTURE_SCREENSHOTS).toBe('1')
|
|
189
|
-
expect(environment?.commandEnvironment.PLATFORM_PORTAL_BASE_URL).toBe(baseUrl)
|
|
190
|
-
expect(environment?.commandEnvironment.OM_TEST_EMAIL_CAPTURE_PATH).toBe(
|
|
191
|
-
path.join(projectRootDirectory, '.ai', 'qa', 'email-capture.jsonl'),
|
|
192
|
-
)
|
|
193
189
|
expect(environment?.commandEnvironment.NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED).toBeUndefined()
|
|
194
190
|
} finally {
|
|
195
191
|
fetchSpy.mockRestore()
|
|
@@ -271,7 +271,6 @@ const EPHEMERAL_ENV_LOCK_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ep
|
|
|
271
271
|
const LEGACY_EPHEMERAL_ENV_FILE_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-env.md')
|
|
272
272
|
const EPHEMERAL_BUILD_CACHE_STATE_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-build-cache.json')
|
|
273
273
|
const EPHEMERAL_CACHE_DB_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-cache.sqlite')
|
|
274
|
-
const EPHEMERAL_EMAIL_CAPTURE_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'email-capture.jsonl')
|
|
275
274
|
const EPHEMERAL_QUEUE_BASE_DIR = path.join(appDirectory, '.mercato', 'queue')
|
|
276
275
|
const PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY = 'ATTACHMENTS_PARTITION_PRIVATE_ATTACHMENTS_ROOT'
|
|
277
276
|
const EPHEMERAL_PRIVATE_ATTACHMENTS_ROOT = path.join(
|
|
@@ -1944,7 +1943,6 @@ function buildReusableEnvironment(
|
|
|
1944
1943
|
BASE_URL: baseUrl,
|
|
1945
1944
|
APP_URL: baseUrl,
|
|
1946
1945
|
NEXT_PUBLIC_APP_URL: baseUrl,
|
|
1947
|
-
PLATFORM_PORTAL_BASE_URL: baseUrl,
|
|
1948
1946
|
NODE_ENV: 'production',
|
|
1949
1947
|
// Share the app server's cache backend with the test process and the
|
|
1950
1948
|
// queue-drain runners it spawns (drainIntegrationQueue children inherit
|
|
@@ -1970,7 +1968,6 @@ function buildReusableEnvironment(
|
|
|
1970
1968
|
OM_ENABLE_ENTERPRISE_MODULES_SSO: process.env.OM_ENABLE_ENTERPRISE_MODULES_SSO ?? enterpriseModulesFlag,
|
|
1971
1969
|
OM_ENABLE_ENTERPRISE_MODULES_SECURITY: process.env.OM_ENABLE_ENTERPRISE_MODULES_SECURITY ?? enterpriseModulesFlag,
|
|
1972
1970
|
OM_TEST_MODE: '1',
|
|
1973
|
-
OM_TEST_EMAIL_CAPTURE_PATH: EPHEMERAL_EMAIL_CAPTURE_PATH,
|
|
1974
1971
|
OM_TEST_AUTH_RATE_LIMIT_MODE: 'opt-in',
|
|
1975
1972
|
// Tests assert on access_logs immediately after CRUD reads; keep the
|
|
1976
1973
|
// blocking write path on inside the integration runtime so tests do
|
|
@@ -3296,7 +3293,6 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
3296
3293
|
BASE_URL: applicationBaseUrl,
|
|
3297
3294
|
APP_URL: applicationBaseUrl,
|
|
3298
3295
|
NEXT_PUBLIC_APP_URL: applicationBaseUrl,
|
|
3299
|
-
PLATFORM_PORTAL_BASE_URL: applicationBaseUrl,
|
|
3300
3296
|
JWT_SECRET: process.env.JWT_SECRET ?? 'om-ephemeral-integration-jwt-secret',
|
|
3301
3297
|
OM_SECURITY_MFA_SETUP_SECRET: process.env.OM_SECURITY_MFA_SETUP_SECRET ?? 'om-ephemeral-integration-mfa-setup-secret',
|
|
3302
3298
|
NODE_ENV: 'production',
|
|
@@ -3325,7 +3321,6 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
3325
3321
|
OM_ENABLE_ENTERPRISE_MODULES_SSO: process.env.OM_ENABLE_ENTERPRISE_MODULES_SSO ?? enterpriseModulesFlag,
|
|
3326
3322
|
OM_ENABLE_ENTERPRISE_MODULES_SECURITY: process.env.OM_ENABLE_ENTERPRISE_MODULES_SECURITY ?? enterpriseModulesFlag,
|
|
3327
3323
|
OM_TEST_MODE: '1',
|
|
3328
|
-
OM_TEST_EMAIL_CAPTURE_PATH: EPHEMERAL_EMAIL_CAPTURE_PATH,
|
|
3329
3324
|
OM_TEST_AUTH_RATE_LIMIT_MODE: 'opt-in',
|
|
3330
3325
|
OM_DISABLE_EMAIL_DELIVERY: '1',
|
|
3331
3326
|
OM_WEBHOOKS_ALLOW_PRIVATE_URLS: process.env.OM_WEBHOOKS_ALLOW_PRIVATE_URLS ?? '1',
|
package/src/mercato.ts
CHANGED
|
@@ -867,10 +867,7 @@ async function buildAllModules(): Promise<Module[]> {
|
|
|
867
867
|
export async function run(argv = process.argv) {
|
|
868
868
|
const [, , ...parts] = argv
|
|
869
869
|
const [first, second, ...remaining] = parts
|
|
870
|
-
await ensureEnvLoaded({
|
|
871
|
-
createIfMissing: first !== 'deploy' && first !== 'telemetry',
|
|
872
|
-
quiet: first === 'deploy' || first === 'telemetry',
|
|
873
|
-
})
|
|
870
|
+
await ensureEnvLoaded({ createIfMissing: first !== 'deploy', quiet: first === 'deploy' })
|
|
874
871
|
|
|
875
872
|
// Handle init command directly
|
|
876
873
|
if (first === 'init') {
|
|
@@ -1335,20 +1332,6 @@ export async function run(argv = process.argv) {
|
|
|
1335
1332
|
return exitCode
|
|
1336
1333
|
}
|
|
1337
1334
|
|
|
1338
|
-
// Handle telemetry command (bootstrap-free) — wires @open-mercato/telemetry
|
|
1339
|
-
// into an app scaffolded before telemetry existed.
|
|
1340
|
-
if (first === 'telemetry') {
|
|
1341
|
-
if (second === 'init') {
|
|
1342
|
-
const { runTelemetryInit } = await import('./lib/telemetry-init')
|
|
1343
|
-
return runTelemetryInit(remaining.filter(Boolean))
|
|
1344
|
-
}
|
|
1345
|
-
console.log('Usage: yarn mercato telemetry init [--dry-run]')
|
|
1346
|
-
console.log(' Wires @open-mercato/telemetry into this app (package.json, .env,')
|
|
1347
|
-
console.log(' instrumentation.ts, next.config.ts, and the API dispatcher).')
|
|
1348
|
-
console.log(' Idempotent and safe to re-run. Use --dry-run to preview changes.')
|
|
1349
|
-
return second && second !== 'help' && second !== '--help' && second !== '-h' ? 1 : 0
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
1335
|
if (first === 'module') {
|
|
1353
1336
|
try {
|
|
1354
1337
|
const subcommand = second
|
|
@@ -1671,8 +1654,6 @@ export async function run(argv = process.argv) {
|
|
|
1671
1654
|
effectiveByQueue.get(queue) ??
|
|
1672
1655
|
concurrencyOverride ??
|
|
1673
1656
|
Math.max(...queueWorkers.map((w) => w.concurrency), 1)
|
|
1674
|
-
const maxStalledCount = Math.max(...queueWorkers.map((w) => w.maxStalledCount ?? 1), 1)
|
|
1675
|
-
const lockDuration = Math.max(...queueWorkers.map((w) => w.lockDuration ?? 0), 0) || undefined
|
|
1676
1657
|
|
|
1677
1658
|
console.log(`[worker] Starting "${queue}" with ${queueWorkers.length} handler(s), concurrency: ${concurrency}`)
|
|
1678
1659
|
|
|
@@ -1681,8 +1662,6 @@ export async function run(argv = process.argv) {
|
|
|
1681
1662
|
queueName: queue,
|
|
1682
1663
|
connection: queueRedisUrl ? { url: queueRedisUrl } : undefined,
|
|
1683
1664
|
concurrency,
|
|
1684
|
-
lockDuration,
|
|
1685
|
-
maxStalledCount,
|
|
1686
1665
|
background: true,
|
|
1687
1666
|
handler: createPerJobWorkerHandler(queueWorkers, createRequestContainer),
|
|
1688
1667
|
})
|
|
@@ -1726,8 +1705,6 @@ export async function run(argv = process.argv) {
|
|
|
1726
1705
|
// never check out more pooled connections than the worker pool holds.
|
|
1727
1706
|
const budgetPlan = await resolveWorkerBudgetPlan([{ queue: queueName!, concurrency: requested }])
|
|
1728
1707
|
const concurrency = budgetPlan.entries[0]?.effective ?? requested
|
|
1729
|
-
const maxStalledCount = Math.max(...queueWorkers.map((w) => w.maxStalledCount ?? 1), 1)
|
|
1730
|
-
const lockDuration = Math.max(...queueWorkers.map((w) => w.lockDuration ?? 0), 0) || undefined
|
|
1731
1708
|
|
|
1732
1709
|
console.log(`[worker] Found ${queueWorkers.length} worker(s) for queue "${queueName}"`)
|
|
1733
1710
|
|
|
@@ -1736,8 +1713,6 @@ export async function run(argv = process.argv) {
|
|
|
1736
1713
|
queueName: queueName!,
|
|
1737
1714
|
connection: queueRedisUrl ? { url: queueRedisUrl } : undefined,
|
|
1738
1715
|
concurrency,
|
|
1739
|
-
lockDuration,
|
|
1740
|
-
maxStalledCount,
|
|
1741
1716
|
handler: createPerJobWorkerHandler(queueWorkers, createRequestContainer),
|
|
1742
1717
|
})
|
|
1743
1718
|
} else {
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# AI Agents, Orchestrators, and Workflows
|
|
2
|
-
|
|
3
|
-
Use typed module contracts for product AI and the workflow engine for durable business processes. Keep model/tool execution, mutation approval, scope, storage, and retries explicit.
|
|
4
|
-
|
|
5
|
-
## Choose the Surface
|
|
6
|
-
|
|
7
|
-
| Need | Use |
|
|
8
|
-
|---|---|
|
|
9
|
-
| In-app conversational or structured domain assistant | Module `ai-agents.ts` plus `ai-tools.ts`. |
|
|
10
|
-
| Low-level MCP/OpenCode or Code Mode work | `ai_assistant` installed contract: `registerMcpTool`, MCP server, OpenCode handlers/config, or the `search`/`execute` Code Mode tools. Do not conflate this with a typed product agent. |
|
|
11
|
-
| Add a few tools/prompt/suggestions to an installed agent | `aiAgentExtensions`. |
|
|
12
|
-
| Replace or disable an installed agent/tool | `aiAgentOverrides` / `aiToolOverrides` or module entry override. |
|
|
13
|
-
| Coding-agent orchestration with files, outcomes, samples, embedded skill, or subagents | Orchestrator file-agent contract; resolve its installed package guide first. |
|
|
14
|
-
| Durable business process, human task, timer, signal, compensation, or event trigger | Workflows module and `om-build-workflow`. |
|
|
15
|
-
| One background AI extraction | Object-mode agent invoked from a scoped command/worker. |
|
|
16
|
-
|
|
17
|
-
## Typed Module Agents and Tools
|
|
18
|
-
|
|
19
|
-
- Put `ai-agents.ts` and `ai-tools.ts` at the module root. Export typed arrays and run `yarn generate`.
|
|
20
|
-
- Give agent IDs `<module>.<agent>` and tool names stable namespaced IDs. Declare provider/model defaults through the framework registry/model factory, not provider SDK singletons.
|
|
21
|
-
- Every data tool has a Zod input schema, tenant/org scope, wildcard-aware `requiredFeatures`, bounded output, and a serializable result.
|
|
22
|
-
- Mark writes `isMutation: true`. Pair mutation-capable agents with `readOnly: false` and a confirmation policy.
|
|
23
|
-
- A write tool calls `prepareMutation`; the durable execute callback performs a command-based, optimistic-lock-aware mutation. Never write directly before approval.
|
|
24
|
-
- Use declarative loop controls/budgets. The wrapper-owned approval guard remains active on every step and execution engine.
|
|
25
|
-
- Validate attachments by type/size/scope. Store outputs through authorized artifact/attachment services with retention and encrypted sensitive metadata.
|
|
26
|
-
|
|
27
|
-
## MCP, OpenCode, and Code Mode
|
|
28
|
-
|
|
29
|
-
- Prefer `defineAiTool` in discovered `ai-tools.ts` for product agents, especially mutation-capable tools. Use low-level `registerMcpTool` only when the requested surface is explicitly the MCP/OpenCode registry. Both require Zod input, matching `moduleId`, wildcard-aware `requiredFeatures` for tenant data, bounded work, and a serializable handler result.
|
|
30
|
-
- OpenCode Code Mode exposes `search` over the generated OpenAPI document and `execute` through sandboxed `api.request()`. Endpoint-level RBAC and documented-feature checks still apply; Code Mode is not an authorization bypass and undocumented/featureless mutation endpoints fail closed.
|
|
31
|
-
- Production MCP uses two-tier auth: the server request carries `x-api-key`, then every tool call carries `_sessionToken`; the runtime resolves the user/session scope and performs per-tool ACL checks on every request. Never cache MCP server instances or ACL context across requests.
|
|
32
|
-
- Ask before editing OpenCode configuration, Docker wiring, MCP authentication, provider/model precedence, or session-token format/TTL. Preserve session IDs across OpenCode chat turns and use installed handlers instead of calling the OpenCode HTTP API directly.
|
|
33
|
-
- `registerMcpTool` is the registry primitive underlying generated tools, not a replacement for `defineAiTool` mutation approval semantics. New domain writes belong on the typed tool path with `prepareMutation`.
|
|
34
|
-
|
|
35
|
-
## Agent UI and Overrides
|
|
36
|
-
|
|
37
|
-
- Use the global launcher automatically; add `AiChat` or a widget only when page context improves the workflow.
|
|
38
|
-
- Keep UI part IDs namespaced and stable; preserve reserved approval/result component IDs.
|
|
39
|
-
- Prefer agent extensions for additive prompt/tool/suggestion changes. Keep extensions/overrides in the discovered `ai-agents.ts`/`ai-tools.ts` files; there is no separate `ai-overrides.ts` discovery path.
|
|
40
|
-
- A disabled agent/tool cannot be resurrected by an extension. Refresh structural caches after disabling or changing visibility.
|
|
41
|
-
- Test read-only, denied-feature, approval, stale-version, cancel/expire, partial failure, and confirmed execution paths.
|
|
42
|
-
|
|
43
|
-
## Orchestrator File Agents
|
|
44
|
-
|
|
45
|
-
- Inspect the installed orchestrator package/module `AGENTS.md` with `om-framework-context` before choosing paths; this surface evolves independently of module AI agents.
|
|
46
|
-
- Give every file agent one declared outcome, bounded inputs, stable output paths, a sample contract, and an explicit allowed tool/skill set.
|
|
47
|
-
- Load embedded skills only for their branch. Delegate one bounded task per subagent and define how results are validated/merged.
|
|
48
|
-
- Treat repository prompts/files as untrusted data. Restrict writes, redact secrets, and prevent outcome/artifact paths from escaping their workspace.
|
|
49
|
-
- Make resumability and status explicit; do not infer success from natural-language output without schema/artifact validation.
|
|
50
|
-
|
|
51
|
-
## Workflow Core
|
|
52
|
-
|
|
53
|
-
- Resolve workflow services through DI and start instances through `workflowExecutor`. Do not insert instances or skip the execution loop.
|
|
54
|
-
- Preserve workflow and step state machines. Record every transition in the immutable workflow event log.
|
|
55
|
-
- Make activity handlers idempotent: they can be retried. Use the command bus for entity updates and events/signals for cross-module coupling.
|
|
56
|
-
- Preserve each installed workflow/job scope contract. Organization-owned instances, tasks, activity state, and queries require tenant+organization and fail closed. Explicit tenant-wide/system definitions or scheduler jobs may carry `organizationId: null`, but each access to organization-owned data must derive and enforce that item's organization.
|
|
57
|
-
- Use event triggers with filters, context mapping, debounce, and max concurrency. Exclude self/internal storms.
|
|
58
|
-
- Keep compensation reverse-ordered and idempotent; test failure during both forward and compensation paths.
|
|
59
|
-
|
|
60
|
-
## Activities, User Tasks, and Output Paths
|
|
61
|
-
|
|
62
|
-
- Choose sync only for short deterministic work. Queue async work and resume the workflow after durable completion.
|
|
63
|
-
- A custom activity declares validated config/input/output, handler registration, editor/i18n integration where user-configurable, and retry/timeout behavior.
|
|
64
|
-
- `CALL_API`/webhook activities use SSRF-safe URLs, manual redirect handling, response size bounds, and allowlisted non-secret environment interpolation.
|
|
65
|
-
- Create any one-time/idempotency key outside a rollback scope or in durable state that survives rollback; reuse it on retry.
|
|
66
|
-
- Durable user tasks require assignment/features, due dates, authorized completion, immutable activity history, and no secret values in task payloads.
|
|
67
|
-
- Write outputs to stable declared activity/artifact paths. Validate path containment and access; clean temporary files while retaining declared deliverables.
|
|
68
|
-
- Emit progress/events for long work and render them through shared progress/UI contracts rather than unbounded polling.
|
|
69
|
-
|
|
70
|
-
## Verification
|
|
71
|
-
|
|
72
|
-
1. Run `yarn generate` and confirm agent/tool/workflow registrations.
|
|
73
|
-
2. Test missing provider/configuration, denied ACL, missing scope, timeout, retry, duplicate, and cancellation.
|
|
74
|
-
3. For AI writes, prove no domain write occurs before approval and a stale approval cannot overwrite newer data.
|
|
75
|
-
4. For workflows, prove event log/state transitions and idempotency across worker restart and injected rollback.
|
|
76
|
-
5. For orchestrators, validate output schema/artifacts and allowed-write boundaries, not just prose.
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# Standalone Architecture and Discovery
|
|
2
|
-
|
|
3
|
-
Use this guide to choose ownership, locate module surfaces, and keep generated discovery correct.
|
|
4
|
-
|
|
5
|
-
## Context Ownership and Scattering
|
|
6
|
-
|
|
7
|
-
The harness is intentionally layered so an agent can assemble precise context without paying for the whole framework:
|
|
8
|
-
|
|
9
|
-
| Layer | Owns | Loading rule |
|
|
10
|
-
|---|---|---|
|
|
11
|
-
| Root `AGENTS.md` | Non-negotiable safety, validation, precedence, and the three-axis router | Load first and always; it is the only initial bundle. |
|
|
12
|
-
| `.ai/guides/*.md` | Stable framework concepts and contracts by area | Load the de-duplicated set selected by the area and primitive axes. |
|
|
13
|
-
| Thin task skills | Branching procedure and links to focused references | Load only matched skills; open only the references needed by the chosen branch. |
|
|
14
|
-
| `.ai/guides/modules/*.md` | Generated identifiers and discovered surfaces for an exact installed module/version | Load only for installed modules named, changed, integrated with, or used as hosts. |
|
|
15
|
-
| `om-framework-context` output | Exact installed instructions, source/types, and bounded search results | Last-mile escalation after app call sites, facts, and concept guides cannot answer the question. |
|
|
16
|
-
| External `open-mercato/skills` | SDLC and delivery workflows | Select independently only when the requested lifecycle needs one. |
|
|
17
|
-
|
|
18
|
-
Match area, work units, and delivery independently, then de-duplicate their union by path and skill. A business one-shot is not one giant context category: split it into units such as entity, command, API, admin UI, public capture, CRM extension, event, and provider, and give each unit only its owning area and contract. Do not preload all module facts, skill references, upstream guides, or installed package source.
|
|
19
|
-
|
|
20
|
-
Keep facts and source in different roles. Facts answer “what identifier or surface exists?”; exact installed source answers “how does this version implement or type the contract?” The latter is read-only evidence, never a writable escape hatch.
|
|
21
|
-
|
|
22
|
-
## Ownership Decision
|
|
23
|
-
|
|
24
|
-
| Need | Choose |
|
|
25
|
-
|---|---|
|
|
26
|
-
| App-specific domain capability | Create `src/modules/<id>/` and register `{ id, from: '@app' }` in `src/modules.ts`. |
|
|
27
|
-
| Additive change to an installed module | Use the smallest UMES mechanism from `.ai/guides/extensions.md`. |
|
|
28
|
-
| Disable/replace a supported installed contract | Use the target module entry's `overrides` in `src/modules.ts`. |
|
|
29
|
-
| Reusable external provider | Add/install a dedicated provider package; do not place provider logic in a generic core module. |
|
|
30
|
-
| Change unsupported by UMES/overrides | Inspect exact installed context, then use `om-eject-and-customize` only with user approval. |
|
|
31
|
-
| Framework defect affecting all consumers | Reproduce against the installed version and report an upstream change; never patch `node_modules`. |
|
|
32
|
-
|
|
33
|
-
## Writable and Read-Only Trees
|
|
34
|
-
|
|
35
|
-
```text
|
|
36
|
-
src/modules/<id>/ writable app modules
|
|
37
|
-
src/modules.ts enabled modules and supported overrides
|
|
38
|
-
.mercato/generated/ generated, never edit
|
|
39
|
-
.ai/guides/modules/ generated facts, never edit
|
|
40
|
-
node_modules/@open-mercato/*/ exact installed packages, read-only
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Do not copy an installed module merely to learn it. Generated facts and the context resolver expose the exact installed source without widening the writable surface.
|
|
44
|
-
|
|
45
|
-
## Canonical Module Shape
|
|
46
|
-
|
|
47
|
-
```text
|
|
48
|
-
src/modules/<id>/
|
|
49
|
-
├── index.ts
|
|
50
|
-
├── data/{entities,validators,extensions,enrichers}.ts
|
|
51
|
-
├── api/**/route.ts
|
|
52
|
-
├── backend/**/{page.tsx,page.meta.ts}
|
|
53
|
-
├── frontend/**/{page.tsx,page.meta.ts}
|
|
54
|
-
├── commands/
|
|
55
|
-
├── subscribers/
|
|
56
|
-
├── workers/
|
|
57
|
-
├── widgets/{injection,injection-table.ts,components.ts}
|
|
58
|
-
├── acl.ts
|
|
59
|
-
├── setup.ts
|
|
60
|
-
├── di.ts
|
|
61
|
-
├── events.ts
|
|
62
|
-
├── search.ts
|
|
63
|
-
├── ce.ts
|
|
64
|
-
├── translations.ts
|
|
65
|
-
├── notifications.ts
|
|
66
|
-
├── encryption.ts
|
|
67
|
-
├── ai-agents.ts
|
|
68
|
-
└── ai-tools.ts
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Create only files required by the capability. Keep the module id plural `snake_case`; keep entity/event/feature/spot/agent/tool identifiers stable once used.
|
|
72
|
-
For the complete current convention-file catalog, load `om-module-scaffold` → `references/discovery-surface-catalog.md`; do not expand this always-routed guide into the full catalog.
|
|
73
|
-
|
|
74
|
-
## Auto-Discovery
|
|
75
|
-
|
|
76
|
-
- Put backend routes under `backend/**/page.tsx`; the module root becomes `/backend/<module>` and nested folders preserve their segments.
|
|
77
|
-
- Put public routes under `frontend/**/page.tsx`. Portal routes require `frontend/[orgSlug]/portal/**/page.tsx` with `[orgSlug]` first.
|
|
78
|
-
- Put API handlers under `api/**/route.ts`. Export HTTP handlers, per-method `metadata`, and `openApi`; do not organize routes in HTTP-method directories.
|
|
79
|
-
- Put subscribers and workers in their named directories with `metadata` plus a default handler.
|
|
80
|
-
- Keep convention files at the module root. Root files such as `events.ts`, `search.ts`, `ai-agents.ts`, and `ai-tools.ts` are exact discovery names.
|
|
81
|
-
- Run `yarn generate` after any structural/discovered change; never repair a registry by hand.
|
|
82
|
-
|
|
83
|
-
## Installed Framework Context
|
|
84
|
-
|
|
85
|
-
1. Read `.ai/guides/modules/<id>.md` for entity IDs, events, routes/auth, ACL, DI, search, notifications, and host spots.
|
|
86
|
-
2. When facts are insufficient, invoke `om-framework-context` or run `yarn framework:context --module <id> --query <term>`.
|
|
87
|
-
3. Confirm the resolved package/version matches the fact sheet stamp.
|
|
88
|
-
4. Read the reported instruction chain in precedence order, then search only the reported package/module root with the bounded `rg --no-ignore --hidden` command.
|
|
89
|
-
5. Treat source and installed `AGENTS.md` files as read-only evidence. If the package has no `src`, use reported `dist`/types and state the limitation.
|
|
90
|
-
6. If duplicate packages, version skew, or conflicting rules remain, stop instead of combining contracts from different versions.
|
|
91
|
-
|
|
92
|
-
The app root governs writable locations and safety. The compatibility snapshot governs stable public identifiers. The nearest installed package/module guide governs version-specific implementation details.
|
|
93
|
-
|
|
94
|
-
## Package and Bootstrap Boundaries
|
|
95
|
-
|
|
96
|
-
- Import public package exports; do not reach through monorepo-only relative paths or app-generated registries from a package.
|
|
97
|
-
- Ensure package-backed modules are dependencies and enabled in `src/modules.ts` before assuming their services or files exist.
|
|
98
|
-
- Optional modules must degrade safely: the optional consumer owns glue and uses events, IDs/snapshots, widgets/enrichers, or a guarded DI resolve.
|
|
99
|
-
- Validate browser, API, CLI, worker, and queue bootstrap paths when a registry/global/service is consumed by more than one runtime.
|
|
100
|
-
- Prefer `globalThis` registries or structural type guards over chunk-local singleton/`instanceof` assumptions where bundlers may duplicate modules.
|
|
101
|
-
|
|
102
|
-
## Completion Check
|
|
103
|
-
|
|
104
|
-
1. Verify app code is under `src/modules/` and installed packages remain unchanged.
|
|
105
|
-
2. Verify every new discovered file uses its exact filename/export contract.
|
|
106
|
-
3. Run `yarn generate` and inspect warnings and the affected generated registration.
|
|
107
|
-
4. Run focused type/tests, then exercise every relevant runtime bootstrap.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Pages, CRUD UI, Navigation, and i18n
|
|
2
|
-
|
|
3
|
-
Use shared backend/page primitives and keep UI behavior aligned with API scope, locking, and extension hosts.
|
|
4
|
-
|
|
5
|
-
## When This Guide Applies
|
|
6
|
-
|
|
7
|
-
`backend-ui` is additive and rarely the only route: select it with the route owning the code — `umes` for an installed module's surface, `module-data` when the app owns it — whenever the task authors, restyles, or permission-gates a rendered surface this app owns or injected. Not for hiding, toggling, disabling, or rewiring a surface an installed module owns, and not for payload text, pagination, or table IDs.
|
|
8
|
-
|
|
9
|
-
## Page Selection
|
|
10
|
-
|
|
11
|
-
Every app page is module-owned and auto-discovered: author it under `src/modules/<id>/{backend,frontend}/**/page.tsx` and run `yarn generate` so it registers into the route registry served by the app's `(backend)`/`(frontend)` catch-all. Never place a `page.tsx`/`page.meta.ts` directly under `src/app/(backend)/**` or `src/app/(frontend)/**` — a page added to the Next.js route group instead of the module renders unregistered, skipping nav injection, ACL feature-gating, and breadcrumbs. The paths below are all relative to the owning `src/modules/<id>/`.
|
|
12
|
-
|
|
13
|
-
| Page | Location and rules |
|
|
14
|
-
|---|---|
|
|
15
|
-
| Backend list/detail/create/edit | `src/modules/<id>/backend/**/page.tsx` plus sibling `page.meta.ts`; require staff auth/features. |
|
|
16
|
-
| Settings | Backend metadata with `pageContext: 'settings' as const` and `navHidden: true`. |
|
|
17
|
-
| Profile | Backend metadata with `pageContext: 'profile' as const`. |
|
|
18
|
-
| Public frontend | `src/modules/<id>/frontend/**/page.tsx`; explicitly declare auth posture in metadata. |
|
|
19
|
-
| Customer portal | `src/modules/<id>/frontend/[orgSlug]/portal/**/page.tsx`; public login/signup/verify/landing pages are `navHidden` without customer auth, authenticated pages require customer auth/features, and only sidebar destinations add `nav`. |
|
|
20
|
-
|
|
21
|
-
List destinations need stable `pageGroup`, `pageGroupKey`, and order. Prefer a registered string icon name in `page.meta.ts` so generated metadata stays serializable; use `lucide-react` components in page-body UI. Hide create/edit/detail destinations from navigation when they are reached from a list.
|
|
22
|
-
|
|
23
|
-
## Default CRUD Completeness
|
|
24
|
-
|
|
25
|
-
For a new editable entity or module, unless the brief explicitly excludes an operation, deliver list, create, view/edit, and delete as one connected slice. The `DataTable` list owns server filter/search controls, a localized add action linking to create, and a stable linked row action to view/edit. `CrudForm` owns create/update/delete, custom-field save/reload/clear, `updatedAt` conflicts, and return navigation. Do not leave a new backend entity reachable only by typing a URL.
|
|
26
|
-
|
|
27
|
-
## DataTable
|
|
28
|
-
|
|
29
|
-
- Use `DataTable` with a stable colon-form `entityId`, explicit typed data/pagination loaded through shared API helpers, and `extensionTableId`. These are host contracts, not cosmetic props; `DataTable` has no `apiPath` prop.
|
|
30
|
-
- Use shared column helpers, `RowActions` with stable action IDs, built-in filter/search/export/column controls, and DataTable bulk-action surfaces.
|
|
31
|
-
- When owning pagination, wire page, page size, total count, and change handlers together. Do not slice a server page again in the client.
|
|
32
|
-
- Use the table's empty state and shared loading/error components. A successful empty result is not an error.
|
|
33
|
-
- Route selected-row and long-running operations through guarded mutations and progress contracts; do not loop direct API writes without cancellation/error reporting.
|
|
34
|
-
|
|
35
|
-
## CrudForm
|
|
36
|
-
|
|
37
|
-
- Use `CrudForm`, typed fields/groups, and `createCrud`/`updateCrud`/`deleteCrud`; use the shared server-error adapter.
|
|
38
|
-
- Pass detail data including `updatedAt` as `initialValues`, allowing the form to protect update and delete automatically.
|
|
39
|
-
- Keep field IDs aligned through request validators, commands, response transforms, custom-field widgets, and translations.
|
|
40
|
-
- Support explicit `null` clearing where the field is clearable; avoid truthy fallbacks that resurrect the old value.
|
|
41
|
-
- Use `crud-form:<entityId>:fields` for injected fields and ensure the read/enricher and save/interceptor paths round-trip the same value.
|
|
42
|
-
- Use shared conflict surfacing for non-`CrudForm` writes.
|
|
43
|
-
|
|
44
|
-
## Data Access and States
|
|
45
|
-
|
|
46
|
-
- Use `apiCall`/`apiCallOrThrow`; use scoped API headers for versions or other request context. Never call raw `fetch` from app backend UI.
|
|
47
|
-
- Use `LoadingMessage`, `ErrorMessage`, `EmptyState`, `Alert`, flash messages, and the standard page/form scaffolding.
|
|
48
|
-
- Preserve the user's input after validation/server errors. Disable duplicate submissions and expose retry only when the operation is safe.
|
|
49
|
-
- Every dialog supports Cmd/Ctrl+Enter submit and Escape cancel. Every icon-only control has an accessible label.
|
|
50
|
-
- Keep server/client locale, timezone, and environment-derived initial render deterministic to prevent hydration mismatches.
|
|
51
|
-
|
|
52
|
-
## Navigation and Overrides
|
|
53
|
-
|
|
54
|
-
- Prefer page metadata for app-owned destinations and menu injection for adding/reordering items owned by another module.
|
|
55
|
-
- Use stable menu item IDs and translation keys. Gate injected items with wildcard-aware ACL checks.
|
|
56
|
-
- Hide or replace installed pages through `src/modules.ts` page overrides; do not delete package code or add a competing route accidentally.
|
|
57
|
-
- If disabling the dashboards module, update the backend landing page to redirect to the first accessible enabled destination, falling back to profile only when necessary.
|
|
58
|
-
|
|
59
|
-
## Design-System Contract
|
|
60
|
-
|
|
61
|
-
- For public/portal or visually substantial app work, use `om-backend-ui-design` → `references/frontend-and-design-system.md` for route-shell, product hierarchy, responsive, accessibility, and UX-state coverage.
|
|
62
|
-
- Reuse existing page, section, form, detail, schedule, messages, notification, chart, KPI, and banner component families before building a local variant.
|
|
63
|
-
- Use semantic design tokens and `StatusBadge` for status. Do not hard-code Tailwind status colors or arbitrary text sizes.
|
|
64
|
-
- Use `FormField` for standalone forms; `CrudForm` owns field layout and must not be wrapped in it. Use `SectionHeader`, `CollapsibleSection`, standard buttons/dialogs, and Lucide icons.
|
|
65
|
-
- Portal record lists use `DataTable`. Never use raw buttons/checkboxes, a button-styled raw `Link`, or `window.confirm`; use the exported primitives and `useConfirmDialog`.
|
|
66
|
-
- Keep responsive behavior, keyboard navigation, focus order, contrast, and reduced-motion behavior intact.
|
|
67
|
-
|
|
68
|
-
## Translation Contract
|
|
69
|
-
|
|
70
|
-
- Use `useT()` in client components and `resolveTranslations()` on the server.
|
|
71
|
-
- Put app translations in module/app locale files using stable namespaced keys. Translate titles, actions, placeholders, validation, empty/error states, notifications, and navigation.
|
|
72
|
-
- Declare `translations.ts` only for entity fields that use the Translation Manager and run `yarn generate` after changing it.
|
|
73
|
-
- Do not place translated output in stable machine identifiers, API enums, logs, or provider protocol values.
|
|
74
|
-
|
|
75
|
-
## Verification
|
|
76
|
-
|
|
77
|
-
1. Exercise permitted and forbidden roles, including wildcard grants.
|
|
78
|
-
2. Exercise loading, empty, validation error, server error, conflict, success, and delete flows.
|
|
79
|
-
3. Save, reload, edit, clear nullable fields, and verify the API payload and rendered state agree.
|
|
80
|
-
4. Check keyboard and narrow-width behavior; run affected integration tests through real API fixtures.
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# Module and Data Contracts
|
|
2
|
-
|
|
3
|
-
Use this guide for entities, APIs, commands, scoping, compatibility, migrations, events, workers, search, and cache. Use `customers` as the CRUD reference after resolving its installed source.
|
|
4
|
-
|
|
5
|
-
## Entity and Scope Contract
|
|
6
|
-
|
|
7
|
-
- Define entity classes together in `src/modules/<id>/data/entities.ts`; import decorators from `@mikro-orm/decorators/legacy` and ORM types from the installed MikroORM package.
|
|
8
|
-
- Give organization-owned business rows `tenant_id` and `organization_id` columns plus a composite index suitable for their common filters. Derive scope from authenticated context, never request payloads. Preserve an installed tenant-wide/system contract only when it explicitly authorizes nullable organization scope; such code must not widen into organization-owned data.
|
|
9
|
-
- Give new user-editable rows `updated_at` with create/update behavior. Return it as `updatedAt` from list/detail APIs.
|
|
10
|
-
- Use UUID primary keys, explicit scalar FK IDs, and module-prefixed plural table names. Do not create cross-module ORM relations.
|
|
11
|
-
- Store sensitive/PII fields through `encryption.ts` `defaultEncryptionMaps`; use the framework decryption find helpers with both scope IDs. Add a deterministic hash sibling only when equality lookup requires it.
|
|
12
|
-
- Model nullable/optional/clearable fields consistently through validator, command, entity, response, and form. Test create, edit, reload, and clearing to `null`.
|
|
13
|
-
|
|
14
|
-
## Migration Workflow
|
|
15
|
-
|
|
16
|
-
1. Change `data/entities.ts` and any validator/command/response contracts.
|
|
17
|
-
2. Run `yarn generate` if discovery or entity registration changed.
|
|
18
|
-
3. Run `yarn db:generate` as a schema-diff probe.
|
|
19
|
-
4. Review every emitted statement; retain only the intended module change and update that module's `.snapshot-open-mercato.json` to the post-change schema.
|
|
20
|
-
5. Never edit a shipped migration. Add a corrective migration.
|
|
21
|
-
6. Ask before `yarn db:migrate`; normal delivery includes migration plus snapshot without mutating the user's database.
|
|
22
|
-
|
|
23
|
-
## CRUD Route Contract
|
|
24
|
-
|
|
25
|
-
Create handlers under `api/<resource>/route.ts` and build them with the installed `makeCrudRoute` contract:
|
|
26
|
-
|
|
27
|
-
- import `makeCrudRoute` from `@open-mercato/shared/lib/crud/factory`;
|
|
28
|
-
|
|
29
|
-
- `metadata`: per-method `requireAuth` and `requireFeatures`;
|
|
30
|
-
- `orm`: entity, id field, tenant/org fields, and explicit soft-delete field (including `null` when absent);
|
|
31
|
-
- `list`: Zod query schema, stable colon-form `entityId`, fields including `updated_at`, scoped filters, stable response transform, and custom-field decoration when needed;
|
|
32
|
-
- `actions.create`, `actions.update`, `actions.delete`: command IDs, raw schemas, scoped input mapping, responses, and statuses;
|
|
33
|
-
- `indexer: { entityType }`: query-index coverage;
|
|
34
|
-
- `enrichers: { entityId }`: only when this route intentionally exposes the enricher host.
|
|
35
|
-
|
|
36
|
-
Export the factory's handlers and a matching `openApi` document as a separate route export. `openApi` is not a `makeCrudRoute` option. Build it with `createCrudOpenApiFactory` and `createPagedListResponseSchema` from `@open-mercato/shared/lib/openapi/crud`, or provide a typed `OpenApiRouteDoc` from `@open-mercato/shared/lib/openapi`. Do not use the stale flat `create`/`update`/`del` factory shape, a top-level `requireAuth`, or an API file organized by HTTP-method directory.
|
|
37
|
-
|
|
38
|
-
Reject malformed ID lists and filters explicitly. Preserve existing response keys; normalize custom fields deliberately and test compatibility when changing prefixed keys.
|
|
39
|
-
|
|
40
|
-
## Commands and Custom Writes
|
|
41
|
-
|
|
42
|
-
- Put domain mutations in commands so audit, undo, events, cache invalidation, and indexing share one path. Routes validate and dispatch; they do not reproduce writes.
|
|
43
|
-
- For custom write/action routes, run registered mutation guards before mutation, merge guarded payload changes, and run post-success callbacks after commit while logging callback failures.
|
|
44
|
-
- Enforce command-level optimistic locking for action/sub-resource endpoints. Guard the aggregate parent when lines share a parent version.
|
|
45
|
-
- Wrap multi-phase scalar/relation work with `withAtomicFlush(..., { transaction: true })`. Keep CRUD side effects and cache invalidation after the transaction commits.
|
|
46
|
-
- Emit both forward and undo side effects with the same index/cache aliases when undo exists.
|
|
47
|
-
- Make retries and idempotency explicit. Do not advance external cursors, one-time keys, or recovery state until the durable unit of work commits.
|
|
48
|
-
|
|
49
|
-
## Runtime Logging
|
|
50
|
-
|
|
51
|
-
- Use `createLogger('<module>')` from `@open-mercato/shared/lib/logger` in runtime/server/module code; use `.child({ component, ...context })` for stable local context.
|
|
52
|
-
- Keep messages stable and put dynamic values in structured metadata; pass caught errors under `err`. Omit or redact credentials, tokens, secrets, PII, and payload bodies.
|
|
53
|
-
- Do not add raw `console.*` calls to runtime/server/module code. Intentional terminal output in CLI/build scripts and test-local console spies remain valid when that runtime requires them.
|
|
54
|
-
|
|
55
|
-
## Optimistic-Lock UI Contract
|
|
56
|
-
|
|
57
|
-
- `CrudForm` derives the update/delete header from `initialValues.updatedAt`; ensure the detail payload supplies it.
|
|
58
|
-
- A custom client mutation wraps the call with the framework's scoped request-header helper and `buildOptimisticLockHeader(record.updatedAt)`.
|
|
59
|
-
- Surface 409s through the shared record-conflict UI. Do not silently retry over newer data.
|
|
60
|
-
- If a parent form mutates children, override the header per child with that child's version; do not reuse the parent version.
|
|
61
|
-
|
|
62
|
-
## ACL and Setup
|
|
63
|
-
|
|
64
|
-
- Declare stable `<module>.<capability>` features in `acl.ts` and their dependency relationships when applicable.
|
|
65
|
-
- Gate API methods and pages declaratively with `requireFeatures`; never gate by mutable role names.
|
|
66
|
-
- Grant new features in `setup.ts` `defaultRoleFeatures` for the intended default roles, then run `yarn mercato auth sync-role-acls` for existing tenants.
|
|
67
|
-
- Use the wildcard-aware matcher wherever raw feature arrays are evaluated; `module.*` and `*` must satisfy concrete grants.
|
|
68
|
-
- Make `onTenantCreated`, `seedDefaults`, and provider setup idempotent. Keep examples in `seedExamples`.
|
|
69
|
-
|
|
70
|
-
## Cross-Module Mechanism
|
|
71
|
-
|
|
72
|
-
| Need | Use |
|
|
73
|
-
|---|---|
|
|
74
|
-
| Side effect after another module changes | Typed event + subscriber owned by the optional consumer. |
|
|
75
|
-
| Display/read another module's data | Widget injection plus response enricher. |
|
|
76
|
-
| Durable historical reference | Scalar ID plus snapshot; resolve live data only when available. |
|
|
77
|
-
| Add app-owned data linked to installed entity | Separate extension entity in `data/extensions.ts`. |
|
|
78
|
-
| Optional service call | Guarded/soft DI resolve in the consumer and a defined degraded result. |
|
|
79
|
-
|
|
80
|
-
## Events, Notifications, Workers, Search, and Cache
|
|
81
|
-
|
|
82
|
-
- Declare typed events in `events.ts` with `createModuleEvents(... as const)` before emitting them. Keep IDs past-tense and stable.
|
|
83
|
-
- Use persistent idempotent subscribers for retried side effects; use ephemeral subscribers for local reactive work. Verify the host module can be absent when optional.
|
|
84
|
-
- Declare notification types/renderers/handlers through their registries; keep notification IDs stable and ACL-aware.
|
|
85
|
-
- Give every worker discovered metadata, an idempotent handler, bounded concurrency/retry behavior, scoped serializable payloads, and commands for domain writes. Use `ProgressJob` for user-visible bulk/long work. Exact cache/queue imports, tenant context, worker shape, retry semantics, and operator commands live in `om-module-scaffold` → `references/runtime-cache-and-queues.md`.
|
|
86
|
-
- Configure `search.ts`; use deterministic convergence polling or reindex assertions rather than arbitrary sleeps.
|
|
87
|
-
- Resolve cache through DI and mirror the host scope in keys/tags: tenant+organization for organization-owned data, or an explicitly authorized tenant-wide key for tenant-wide state. Invalidate every successful write/undo/sub-resource path after commit; non-request runtimes establish the tenant cache context explicitly.
|
|
88
|
-
- Add module CLI commands through the discovery contract and test the compiled package path, not only TypeScript source.
|
|
89
|
-
|
|
90
|
-
## Frozen Surfaces
|
|
91
|
-
|
|
92
|
-
Treat API routes, public imports/signatures, DB schema, event/entity/ACL/DI/widget/notification/AI IDs, CLI commands/flags, and generated bootstrap exports as compatibility surfaces. Prefer additive fields and aliases. A rename/removal needs an explicit deprecation bridge and migration plan.
|