Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9fc2a6e
chore(deps): bump typescript to 7.0.2
zaxovaiko Jul 30, 2026
d965bba
test: split unit and integration test tiers
zaxovaiko Jul 30, 2026
24f3228
fix(tooling): keep generated migrations out of the newline hook
zaxovaiko Jul 30, 2026
0488f1d
docs(rules): split the code standard into always-on core plus on-dema…
zaxovaiko Jul 30, 2026
ac23878
ci: serialise the two integration suites
zaxovaiko Jul 30, 2026
cc7d352
test: log funnel payload to diagnose the ci-only analytics failure
zaxovaiko Jul 30, 2026
bf794a9
test: log funnel service inputs in ci
zaxovaiko Jul 30, 2026
b58f383
test: format debug logging
zaxovaiko Jul 30, 2026
06f597b
test: log funnel service output in ci
zaxovaiko Jul 30, 2026
d4990a6
test: dump compiled funnel source in ci
zaxovaiko Jul 30, 2026
4b631b9
test: log funnel module url in ci
zaxovaiko Jul 30, 2026
d8ca589
test: log funnel module url in ci
zaxovaiko Jul 30, 2026
2de792a
revert: back to typescript 6.0.3
zaxovaiko Jul 30, 2026
e1c786a
chore: merge dev
zaxovaiko Jul 30, 2026
0942ecf
fix(analytics): assert the nullable first-stage drop-off rate in the e2e
zaxovaiko Jul 30, 2026
f80193f
Merge branch 'dev' into chore/rules-and-test-split
zaxovaiko Jul 31, 2026
a302839
chore(rules): finish split and test tiers
zaxovaiko Jul 31, 2026
58f37bc
chore(rules): consolidate conventions guidance
zaxovaiko Jul 31, 2026
71c2752
chore(react): align hooks with react compiler
zaxovaiko Jul 31, 2026
b6b7064
chore(repo): resolve conflicts with dev
zaxovaiko Aug 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"oss-boundaries/no-engine-to-domain": "error",
"oss-module-shape/module-file-placement": "error",
"oss-module-shape/layer-file-naming": "error",
"oss-module-shape/int-test-file-naming": "error",
"oss-module-shape/no-inline-pg-enum": "error",
"oss-module-shape/no-relative-zone-escape": "error",
"oss-module-shape/no-reinfer-imported-schema": "error",
Expand Down
2 changes: 1 addition & 1 deletion .rulesync/commands/scaffold-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Run `pnpm gen module $ARGUMENTS` (args: `<domain> <name>`, eg `casino tournament
The scaffold ships a buildable module - a `list` route wired end to end (contract -> router -> service) over a sample table - so `pnpm regen && pnpm verify` is green immediately. The generator marks edit regions with `// AGENT: implement here` - fill those, leave the wiring alone:

1. `plugin.ts` - verify the module id + any default adapter bindings (`ctx.provide(TOKEN, () => new DefaultImpl())`).
2. `schema/index.ts` - Drizzle tables (`propose-table-change` via MCP first; see `db-conventions`).
2. `schema/index.ts` - Drizzle tables (`propose-table-change` via MCP first; see `docs/standards/database.md`).
3. `contract/index.ts` - Zod input/output schemas for the routes (the single source of wire truth).
4. `service/<name>.service.ts` - business logic; inject `DRIZZLE` + `EVENT_BUS` + adapter ports via the constructor; never inline fetch/SQL. Audit every mutation.
5. `router/index.ts` - oRPC routes with imported schemas; admin routes call `await adminGuard.assert(context)` first.
Expand Down
279 changes: 59 additions & 220 deletions .rulesync/rules/conventions.md

Large diffs are not rendered by default.

119 changes: 0 additions & 119 deletions .rulesync/rules/db-conventions.md

This file was deleted.

16 changes: 9 additions & 7 deletions .rulesync/rules/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ globs:

Canonical brief for AI agents and humans. Per-tool files (`AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md`, `.codex/config.toml`, subagent + command mirrors) are generated by [rulesync](https://github.com/dyoshikawa/rulesync) from `.rulesync/`. Edit the source, run `pnpm gen:agents`. Never hand-edit generated files.

Sibling rules (load on demand; don't reopen settled questions): `conventions` (code standard), `clean-architecture` (module layering, DI, ports, shared helpers), `messaging-and-microservices` (async seams, command vs event vs job, outbox), `db-conventions` (SQL / Drizzle).
Sibling rules (load on demand; do not reopen settled questions): `conventions` (the always-on code and database standard, with a table routing to the matching deep-dive file in `docs/standards/`), `messaging-and-microservices` (async seams, command vs event vs job, outbox). Module layering, DI, ports and the shared-helper table live in `docs/standards/module-structure.md`.

## Mission

Expand Down Expand Up @@ -61,13 +61,13 @@ extensions.config.ts # the single registry of enabled plugins
- **Extend/override an existing module** -> overlay plugin: `pnpm gen plugin <name>` -> `extensions/<name>/plugin.ts` (repo root here; the consumer's app when deployed).
- **New HTTP route** -> the module's `router/index.ts` via `pnpm gen route <module> <method> <path>`. Player routes resolve the caller from `x-user-id`; admin routes MUST be guarded (next).
- **Admin-only route** -> `plugin.ts` resolves `AdminGuard` (`c.get(ADMIN_GUARD)`, seeded by `createApp`) and passes it into the router; `await adminGuard.assert(context)` is the handler's FIRST line. The single admin-enforcement point - never re-implement the role check.
- **New DB table** -> a Drizzle `pgTable` in the module's `schema/index.ts`; run `propose-table-change` (MCP) first, then `pnpm regen`. See `db-conventions`.
- **New DB table** -> a Drizzle `pgTable` in the module's `schema/index.ts`; run `propose-table-change` (MCP) first, then `pnpm regen`. See `docs/standards/database.md`.
- **Reference / seed data** (roles, command configs, default tags, static lookup rows) -> `<module>/seed/index.ts` exporting a `seed<Module>(db: DrizzleDb): Promise<void>` function. Wire the subpath export (`@openora/core/<domain>/seed/<module>`) in `packages/core/package.json` + `tsconfig.json`, then import and call from `tools/db/seed.ts`. Use `onConflictDoNothing()` — seed is always idempotent. Never inline seed rows in a migration or in `tools/db/seed.ts` directly. Reference: `iam/seed/`, `pam/tag/seed/`, `engagement/chat-commands/seed/`.
- **Reusable Zod schema** -> `packages/core/src/contracts/schemas/<namespace>.ts`. Module-local schemas in the module's `contract/`.
- **Enum / status value set** -> a values + schema + type triple on the contract surface (cross-domain: core `contracts/schemas/`; domain-local: the module's `contract/`), pgEnum derived from the tuple. `conventions` section 3 + `db-conventions` > Enums.
- **Enum / status value set** -> a values + schema + type triple on the contract surface (cross-domain: core `contracts/schemas/`; domain-local: the module's `contract/`), pgEnum derived from the tuple. `docs/standards/types.md` + `docs/standards/database.md` > Enums.
- **Cross-module event** -> declare the payload in `domainEventSchemas` (`packages/core/src/contracts/schemas/events.ts`), emit via `EventBus`, subscribe with `ctx.events.on(...)`. ADR-0010; detail in `messaging-and-microservices`.
- **Frontend UI** -> NOT here (headless). Consumer builds it over HTTP via `@openora/core/react`.
- **New data hook** -> `packages/core/src/react/hooks/` (domain-specific: that domain's `react/` dir). Hand-write `useMemo`/`useCallback` for stability-contract returns (consumer's React Compiler skips `node_modules`) - `conventions` section 7.
- **New data hook** -> `packages/core/src/react/hooks/` (domain-specific: that domain's `react/` dir). React Compiler owns memoization - `docs/standards/react-sdk.md`.
- **Operator config** (feature flags, brands, RG defaults) -> `platform-config.yaml`/`.json` via `loadPlatformConfig()` + `PlatformConfigSchema`, bound as `PLATFORM_CONFIG`. ADR-0013.
- **Third-party integration** (PSP, KYC, aggregator, chat) -> adapter interface + `createToken<Adapter>` in `packages/core/src/contracts/adapters/<category>.ts`, impl in the owning module's `adapters/<vendor>/`, bound in `plugin.ts` via `ctx.provide(TOKEN, () => new Impl())`. Never inline `fetch`/SDK calls.
- **Background task** -> the `JOB_QUEUE` seam: `enqueue(queue('name'), payload, { idempotencyKey, delayMs, attempts, backoff, orderingKey })`; a worker overlay registers the handler via `ctx.jobs.worker(...)`. At-least-once: handlers idempotent (DB guard for money). ADR-0014.
Expand All @@ -79,7 +79,7 @@ Cross-cutting basics (kebab files, PascalCase types, `<Name>Schema` + inferred `

- Packages: `@openora/<kebab>`. Public API = package/subpath entry + read-only `/schema`; internals are a lint error.
- oRPC routers namespaced by module (`wallet.transactions.list`).
- SQL / Drizzle identifiers: `db-conventions`.
- SQL / Drizzle identifiers: `docs/standards/database.md`.

## Dependency rules (two-layer enforcement, both in `pnpm verify`)

Expand All @@ -96,7 +96,7 @@ Lint-enforced cross-cutting bans in `conventions`: `any` outside tests, `interfa

- Ad-hoc/duplicated Zod schemas in routers/services - schemas live in the module's `contract/` or core contracts; derive with `.pick/.omit/.partial/.extend/.merge`, don't re-type fields.
- Re-exporting types "to be nice" - import from where defined.
- SQL anti-patterns (bare `timestamp()`, CamelCase identifiers, hand-edited migrations) - `db-conventions`.
- SQL anti-patterns (bare `timestamp()`, CamelCase identifiers, hand-edited migrations) - `docs/standards/database.md`.

## Run locally

Expand All @@ -107,7 +107,9 @@ pnpm setup # first time: docker + db + mcp + summary
pnpm dev # turbo dev (docs, mcp)
pnpm regen # tsconfig paths + openapi emit + drizzle generate + catalog
pnpm db:seed # demo data (idempotent; admin@oss.dev / password123)
pnpm verify # the full gate: every check:* + test:unit + test:tools, in parallel
pnpm verify # the full gate: every check:* + test:unit + test:integration + test:tools, in parallel
pnpm test:unit # infra-free suite (~4s); *.int.test.ts run in test:integration (docker pg + redis)
pnpm db:setup:test:fresh # recreate the shared e2e db after editing an already-applied migration
pnpm check:boundaries # just the whole-graph boundary + cycle gate
pnpm check:drift # catalog/openapi staleness (CI-only; not part of verify)
pnpm fix:lint # oxlint --fix; pair with fix:format
Expand Down
Loading
Loading