Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,28 @@

### Convex TypeScript deep-instantiation workaround

- Canonical guide: `docs/convex-type-safety-playbook.md`
- If Convex typecheck hits `TS2589` (`Type instantiation is excessively deep and possibly infinite`) at generated refs like `api.foo.bar` or `internal.foo.bar`, prefer a **local escape hatch** instead of broad weakening.
- First keep call signatures shallow at the hot spot:
- cast `ctx.scheduler.runAfter`, `ctx.runQuery`, or `ctx.runMutation` to a local shallow function type.
- If merely referencing `api...` / `internal...` still triggers `TS2589`, use `makeFunctionReference("module:function")` from `convex/server` at that call site instead of property access on generated refs.
- Keep this workaround **localized only to pathological sites**. Continue using generated `api` / `internal` refs normally elsewhere.
- Expect hidden follow-on errors: rerun `pnpm --filter @opencom/convex typecheck` after each small batch of fixes, because resolving one deep-instantiation site can reveal additional ones.

## Convex Type Safety Standards

- Read `docs/convex-type-safety-playbook.md` before adding new Convex boundaries.
- Frontend runtime/UI modules must not import `convex/react` directly. Use local adapters and wrapper hooks instead.
- Keep Convex refs at module scope. Never create `makeFunctionReference(...)` values inside React components or hooks.
- Do not add new `getQueryRef(name: string)`, `getMutationRef(name: string)`, or `getActionRef(name: string)` factories.
- Backend cross-function calls should use generated `api` / `internal` refs by default. Only move to fixed `makeFunctionReference("module:function")` refs after a real `TS2589` hotspot is confirmed.
- Keep unavoidable casts localized to adapters or named backend hotspot helpers. Do not spread `as unknown as`, `unsafeApi`, or `unsafeInternal` through runtime code.
- After changing a boundary, update the relevant hardening guard:
- `packages/convex/tests/runtimeTypeHardeningGuard.test.ts`
- `apps/web/src/app/typeHardeningGuard.test.ts`
- `apps/widget/src/test/refHardeningGuard.test.ts`
- `packages/react-native-sdk/tests/hookBoundaryGuard.test.ts`

### Tests

- Convex targeted file:
Expand Down
12 changes: 11 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Thanks for contributing to Opencom. This guide covers everything you need to get
- [Security & Operations](docs/open-source/security-and-operations.md)
- [Data Model Reference](docs/data-model.md)
- [Backend API Reference](docs/api-reference.md)
- [Convex Type Safety Playbook](docs/convex-type-safety-playbook.md)
- [Scripts Reference](docs/scripts-reference.md)

## Development Setup
Expand Down Expand Up @@ -87,24 +88,33 @@ opencom/
- Visitor endpoints require `sessionToken` validated via `resolveVisitorFromSession()`.
- System/bot actions use `internalMutation` to bypass external auth.
- Use `v.any()` sparingly and document in `security/convex-v-any-arg-exceptions.json`.
- Follow `docs/convex-type-safety-playbook.md` for all new Convex boundaries.
- Default backend-to-backend calls to generated `api` / `internal` refs.
- If a call site hits `TS2589`, keep the workaround local:
- shallow `ctx.runQuery` / `ctx.runMutation` / `ctx.runAction` / `runAfter` helper first
- fixed typed `makeFunctionReference("module:function")` only if the generated ref still fails
- Do not add new generic `get*Ref(name: string)` factories or broad `unsafeApi` / `unsafeInternal` aliases.

### Frontend (Web / Landing)

- Next.js App Router.
- Tailwind CSS + Shadcn UI components from `@opencom/ui`.
- React context for auth (`AuthContext`) and backend connection (`BackendContext`).
- Convex React hooks for data fetching (real-time subscriptions).
- Use local Convex wrapper hooks and adapters for data fetching.
- Do not import `convex/react` directly into feature/runtime UI modules.

### Widget

- Vite-built IIFE bundle. Target: <50KB gzipped.
- No external dependencies beyond Convex client.
- All visitor calls thread `sessionToken`.
- Use `apps/widget/src/lib/convex/hooks.ts` plus feature-local wrappers instead of direct `convex/react` imports in runtime files.

### Mobile

- Expo / React Native.
- Same auth patterns as web (Convex Auth + BackendContext).
- New mobile Convex usage should follow the same local-wrapper pattern as web/widget instead of adding new direct screen/context-level hook usage.

## Verification Workflow

Expand Down
Loading
Loading