Internal Platform Requirement · v1.0

Spec Studio — BA-Owned Application Factory

A system where a functional Business Analyst authors the complete application specification — screens, fields, validations, workflows, actions, schedules — and a deterministic generator produces the backend, database, API integrations and frontend wiring. AI is used only where it is safe: one-time construction of the platform itself, and visual UI generation via Stitch.

Date: 04 Jul 2026 Owner: Balpreet Singh Status: For Review First target: Omara Digitech ecosystem (6 sites · QmaxPay · E-Mart · 1Q1Pay · Fincomax · ERP)

1Goal & Non-Goals

Goal

Non-Goals (explicitly out)

2Core Principles

P1 — The BA never types an identifier. Every reference (field, screen, status, role, action) is picked from a dropdown fed by the spec itself. Free text exists only for labels, messages and template copy. This single rule is what makes 100% BA ownership possible.
P2 — Verb palette contract. The BA composes flows from a finite palette of business verbs (wallet.debit, notify.send, approval.request, provider.call, status.transition…). Developers publish new verbs once; the BA reuses them forever. BA owns composition; devs own primitives.
P3 — One canonical spec. All authoring surfaces compile continuously to versioned YAML in git. The BA never sees YAML — it is the storage format, not the interface. Git gives diffing, review, rollback and sign-off traceability.
P4 — Validate at the moment of authoring. A spec linter runs on every change and shows errors in-context ("this screen references a deleted field"). Invalid specs cannot be published.
P5 — Generate the boring, interpret the changing. CRUD, APIs, models, validation → generated code. Workflows → executed by a small runtime engine directly from the spec, so a flow change is a spec publish, not a redeploy.
P6 — A spec publish is a deploy. Draft → validate → review → publish → generate → migrate (staging first). No live-editing production behaviour.

3Architecture — Who Produces What

Four producers, one application. The tags below are used throughout this document: BA-authored Deterministic generator AI (Stitch) Dev-owned primitive

BA-authored Spec Studio

Entities · fields · enums · validations · logical screens (form + list) · status lifecycles · workflows & action chains · schedules · menus & RBAC · report definitions · notification & document templates · master/seed data
▼  compiles to YAML in git · validated · published

Deterministic generator (one-time AI-built, then frozen & versioned)

Backend — complete: REST APIs, auth, RBAC guards, validation, services, workflow runtime hooks, audit log Database — complete: schema, indexes, migrations (spec-diff driven), seed & master data Crons: scheduled jobs from spec triggers Integration services: adapter scaffolds + routing for external APIs FE API layer: typed clients, hooks, binding manifest Tests: validation, workflow-path & transition tests with SRS traceability
▼  binding manifest + design system  |  ▼ verb implementations

AI (Stitch) Visual UI   ·   Dev-owned Engine Primitives

Stitch: screen visuals generated from the logical screen spec + brand design system, then wired to generated typed API hooks via the binding manifest.
Devs: wallet/ledger engine, transaction routing, settlement & reconciliation, provider integrations (AEPS/DMT/BBPS/UPI/PG), PDF/invoice engine — exposed to the BA only as verbs.
Why this split works: the visual layer is the only place where AI variability is acceptable (a slightly different-looking screen is fine; a slightly different settlement calculation is not). Everything with business meaning flows through the deterministic path.

4What the Generator Produces

OutputContentsNotes
Backend (complete)NestJS service per app: REST endpoints per entity/screen action, request validation from spec rules, authentication, module- and field-level RBAC guards, service layer invoking verb primitives, workflow-engine integration, audit logging on every mutation, CSV import/export where flagged.

Per-entity CRUD defaults (always generated): pagination (capped), sorting, filtering, Postgres full-text search, bulk upsert with per-row error reporting, bulk deactivate, soft delete (deleted_at; hard delete only where spec says so), idempotency keys on all money-touching endpoints, rate limiting per route class.

Observability (always generated): structured JSON logs (pino) with end-to-end request IDs, OpenTelemetry traces, Prometheus metrics, health/readiness endpoints.
Generated code is never hand-edited. Custom logic enters only via extension points (§8).

Redis policy: queues (BullMQ), sessions, OTPs, rate-limit counters and idempotency keys by default. Read caching is opt-in per entity via a spec flag (cache-aside, TTL) for change-tolerant data only (masters, catalogs, dashboards) — never wallet balances or ledger. Postgres is always the single source of truth; no write-behind.
Database (complete)PostgreSQL schema, constraints & indexes, spec-diff-driven migrations, destructive-change detection (blocked without explicit confirmation), seed/master data packaged from the studio (GST rates, state codes, categories, compliance catalogs), numbering series (sequential GST invoice numbers).Migrations run staging-first via the publish gate.
Crons / scheduled jobsEvery on-schedule trigger in the spec becomes a queued job: nightly settlement, compliance reminders, KYC document expiry, abandoned-cart flags, low-balance alerts.BullMQ + Redis; retries, idempotency keys and dead-letter queues generated by default.
External API integration servicesAdapter-pattern scaffolds per provider: interface, config/credential slots, request/response mapping stubs, webhook receivers, callback verification, retry policy, sandbox/production switching.Adapter internals are dev-written (provider quirks are not spec-able); everything around them is generated.
FE API integration layerTyped API clients + React Query hooks per endpoint, auth/session handling, error & loading conventions, and a binding manifest: screen → fields → validations → actions → API calls, consumed when wiring Stitch-generated UI.This is the contract that lets AI-generated UI stay a thin skin over deterministic behaviour.
Generated testsOne test per validation rule, per legal/illegal status transition, per workflow path; API contract tests per endpoint. Every test carries the SRS requirement ID from the spec (srs_ref).Requirement → spec → code → test traceability for client sign-off (fixed-price insurance).

5The BA Studio — Authoring Surfaces

5.0 At a glance — everything the BA manages: input → storage → UI

Every requirement type the BA provides, where it is stored, and what he sees on screen. Everything below auto-syncs to YAML in git (the canonical spec, §6) — the BA never touches YAML directly.

#What the BA providesStored inUI shown to the BA
1Entities & fields (data dictionary)Grist → YAMLEditable spreadsheet grid
2Field validations (required, format, range, cross-field)Grist (linked to fields) → YAMLEditable grid — field/operator/value via dropdowns
3Enums & dropdown option listsGrist → YAMLEditable grid
4Form screens — sections, fields, visibility rules, buttonsGrist (Screens + Screen-Fields tables) → YAMLEditable table + live screen preview with fake data
5List screens — columns, filters, search, sort, row/bulk actionsGrist → YAMLConfig form + live list preview
6Status lifecycles — statuses, transitions, who can transitionYAML (authored on canvas)State diagram editor (boxes & arrows)
7Workflows & on-click action chainsYAML (authored on canvas)Drag-drop flow canvas with verb palette (§13)
8Schedules — when timed flows run (nightly settlement, reminders)YAML (trigger config)Simple form — frequency/time dropdowns on the flow's trigger node
9Decision tables — commission slabs, tier pricing, eligibilityGrist → YAMLCondition → outcome grid (Excel-style)
10Roles & permissions (module / screen / field level)Grist → YAMLMatrix grid with checkboxes
11Menus & navigation per roleGrist → YAMLTree editor
12Notification templates (SMS / email / push / in-app)Git (via studio editor)Rich-text editor + merge-field dropdowns + preview
13Document / PDF templates (GST invoice, statements, contracts)Git (via studio editor)Template editor + live PDF preview
14Numbering series (invoice no., order no.)Grist → YAMLSmall settings form
15Report definitions — dataset, filters, group-bys, columns, chartGrist → YAMLStructured form + sample output preview
16Master / seed data (GST rates, state codes, categories, compliance catalog)Grist → packaged with appEditable spreadsheet grid
17Import/export flags per entity (CSV bulk upload)Grist → YAMLCheckbox on the entity row
18SRS traceability refs (srs_ref per item)Grist column → YAMLDropdown column on every grid/table

5.1 Surface details

One web application, several surfaces — each matched to the shape of what is being authored. All surfaces write to the same spec and obey P1 (dropdowns only).

SurfaceWhat the BA authorsUI shapeBase (all OSS)
Data gridEntities, fields, enums, field-level validations, permission matrices, master/seed dataSpreadsheet with linked-record dropdowns; bulk entryGrist (self-hosted) or NocoDB, synced to YAML
Logical screen designerForm screens: sections, fields (picked), conditional visibility, validations, buttons/actionsStructured builder + live preview with fake dataCustom (React) + Faker
List screen designerList/table screens: columns, filters, search, sort, bulk & row actions, export flagsConfiguration form + live previewCustom (React) — mostly config, low effort
Status lifecycle editorStatuses, allowed transitions, who may transition, what fires on transitionSmall state diagram (states + arrows)React Flow
Flow canvasWorkflows & action chains from the verb palette; branches, approvals, error/compensation pathsDrag-drop node canvas; every node configured via dropdown formsReact Flow (custom palette)
Decision tablesCommission slabs, tier pricing, eligibility/applicability rulesCondition → outcome grid (Excel-native mental model)Grid with conventions
Template editorsEmail/SMS/push templates; printable documents (GST invoice, statements, contracts) with merge-field pickers and numbering seriesRich text + merge-field dropdowns; PDF previewCustom + pdfmake/Puppeteer
Navigation & RBACMenu tree per role; screen/module accessTree editor + matrix gridCustom (trivial)
Report definitionsDataset (entity + joins), filters, group-bys, aggregates, columns, chart type, exportStructured form (tabular v1; visual composer later)Custom
Dropped from earlier drafts: SurveyJS Creator (paid licence) and form.io builder — no longer needed, since visual layout now comes from Stitch. The studio's screen designer stays logical (what fields, what rules, what actions), not visual.

6Spec Pipeline & Governance

Two roles, strict separation: the BA authors content and publishes to SIT; the Technical PM (TPM) reviews and promotes to UAT and Prod. The BA cannot promote; the TPM cannot edit the spec — every production change passes both pairs of eyes, and git records who published and who promoted each version.

  1. Login & project — BA logs into the studio (roles: BA / TPM / Admin), creates or opens a project. A project = one client app (E-Mart, QmaxPay…) with its own spec, git repo and three environments.
  2. Author in Draft — the BA always edits the single Draft workspace (Screens / Data / Automations tabs), autosaved. Environments are never edited directly — versions are promoted through them, so the three stages can never diverge.
  3. Validate — linter runs on every change: referential integrity, orphan screens, unreachable statuses, missing permissions, unbound actions. Errors shown in-context; publishing blocked while red. Live preview renders screens with fake data.
  4. Publish → SIT (BA) — validation green → immutable version created (git commit + tag, e.g. emart-spec-v13) → CI generates code + migration plan + tests and auto-deploys to the SIT URL. The BA verifies his changes in the actual running application. SIT redeploys on every publish — it may run several versions ahead of Prod.
  5. Promote → UAT (TPM) — TPM reviews the business-language diff, checks SIT, promotes the same immutable version to the UAT URL. This is the URL handed to the client for their UAT window.
  6. Promote → Prod (TPM) — after UAT sign-off; hard gate: destructive migrations require explicit confirmation here. Workflow-only changes (interpreted, P5) skip code deploy entirely.

Environments: each is a fully running copy at its own URL (e.g. emart-sit.… / emart-uat.… / emart.…) with its own database, seed data and provider credentials (sandbox in SIT/UAT, live in Prod). The environment selector in the studio is a viewer: see which version each stage runs, browse it read-only, compare diffs. Rollback = repoint a stage to an earlier tag.

No parallel branches (v1): an urgent Prod fix is a small fast-tracked publish + promotion, not a spec branch — YAML branching/merging is deferred deliberately.

6.1 Spec versioning in git — how it works day-to-day

6.2 Performance defaults — generated, not hoped for

6.3 Error discipline — users only ever see business errors

7Trigger Model

Every workflow starts from exactly one of four triggers — this covers the full SRS surface (settlements, reminders, expiries, webhooks):

TriggerExample from Omara scopeGenerated as
on-action (user clicks)"Confirm order", "Approve KYC", "Initiate payout"API endpoint → workflow run
on-record-changeOrder status becomes Delivered → release commission entryDB-event hook → workflow run
on-scheduleNightly settlement run; compliance calendar reminders; KYC doc expiryCron job (BullMQ repeatable)
on-event (external)PG webhook: payment success/failure; provider callbackWebhook receiver → verified → workflow run

8Extension Points — Dev-Owned Primitives

Domain engines are not spec-expressible and are hand-built once, then exposed to the BA as verbs:

Generated code calls custom hooks only at named extension points (e.g. custom/onOrderConfirm.ts if present). Regeneration is therefore always safe. When the BA needs a missing capability, they raise a "request new verb" item; a dev ships the primitive once and it joins the palette.

9Open-Source / Free Tool Stack

Constraint honoured: no paid licences anywhere. Free cloud tiers only where noted.

ConcernChoiceLicence / cost
BA data gridGrist (self-hosted) — fallback: NocoDB / Baserow OSSApache-2.0 / self-host free
Flow canvas & lifecycle editorReact Flow (custom node palette)MIT
Spec storage & reviewYAML in git (GitHub free) + JSON Schema / AJV validationFree / MIT
GeneratorNode.js + TypeScript; templates via Handlebars/EJS, AST work via ts-morphMIT
Web frontend targetNext.js (also used for the six static brand sites via SSG)MIT
Mobile target (Phase 2)React Native + Expo — deferred; spec stays platform-neutral, shares generated API clientsMIT
Backend targetNestJS (on Express, Node.js runtime) — finalMIT
Database + ORM/migrationsPostgreSQL + Drizzle (or Prisma) with generated spec-diff migrations — final (MongoDB rejected: ledger atomicity, constraints, report joins, spec-diff migrations all favour relational)OSS; Neon free tier already in use
Observabilitypino logs + OpenTelemetry + Prometheus/Grafana/LokiMIT / Apache-2.0 / AGPL (self-host free)
Workflow runtimeCustom interpreter (XState-informed) executing workflow specMIT deps
Jobs / crons / queuesBullMQ + RedisMIT / OSS
Authbetter-auth or Keycloak (if SSO needed)MIT / Apache-2.0
Frontend data layerReact Query + generated typed clients (openapi-typescript)MIT
Visual UIStitch (AI) from logical screen spec + design systemFree
PDF / documentspdfmake or Puppeteer print pipelineMIT / Apache-2.0
Fake data for previewsFaker.jsMIT
NotificationsNodemailer + client-procured SMS/email gateways (SOW puts gateway costs on client); Novu OSS if a hub is wantedMIT / OSS
TestsVitest + Supertest (API), Playwright (E2E)MIT / Apache-2.0
CIGitHub Actions free tierFree

10Testing & Traceability

11Build Plan & Pilot

Wk 1–2
Spec schema + grid surface. Freeze the YAML schema v0 (entities, fields, validations, screens, statuses, flows, triggers). Stand up Grist with linked tables + YAML sync + AJV validator. BA starts authoring real Omara entities immediately. Static websites proceed conventionally in parallel (month-1 SOW deliverable does not need the platform).
Wk 3–4
Generator core. Entities → Postgres schema + migrations; CRUD APIs + RBAC + validation; typed FE clients; generated tests. First Stitch screens bound via the binding manifest.
Wk 5–6
Flow canvas + workflow runtime + triggers. Verb palette v1 (~30–40 verbs drafted from the SRS module lists), status-lifecycle editor, cron/webhook trigger generation, publish gate with staging-first migrations.
Wk 7–8
Pilot module end-to-end: Support Ticketing (exists in all four platforms) — BA specs it, system generates it, Stitch skins it, generated tests pass, deployed to staging. Schema learnings folded back before scaling. Then: notification/document templates, report definitions, list-screen designer polish.
Wk 9+
Scale to QmaxPay wave (SOW wave 2), then E-Mart, then 1Q1Pay/Fincomax/ERP. Dev team builds engine primitives (wallet, routing, settlement, adapters) in parallel from week 3.

Deferred deliberately: React Native renderer, visual dashboard composer, AI spec-drafting copilot (add only after the BA is fluent in manual authoring).

12Decisions — Locked confirmed 04 Jul 2026

DecisionLocked choiceRationale
BA grid toolGrist (self-hosted)Strongest linked-record dropdowns + API for YAML sync. NocoDB is the fallback only if a 1-day spike surfaces a blocker.
Backend flavourNestJS (on Express)Structure, guards and DI make it the friendlier deterministic-generation target; consistency beats raw speed here.
Full stack (final)Next.js · NestJS · PostgreSQL; React Native + Expo deferred to Phase 2"MERN with the M upgraded" — all-TypeScript, Node runtime, React everywhere; Postgres over MongoDB for ledger integrity, constraints and reporting. Redis = queues + ephemera by default, read cache opt-in per entity.
Workflow runtimeCustom interpreter with XState semantics (guards, compensation)Full control over execution; keeps the BA-facing spec vocabulary small instead of inheriting a library's model.
Verb palette v1Drafted — see §13Derived from the Omara SRS module lists; to be finalised in a dedicated review session with the BA.
Repo layoutOne platform repo + one generated repo per client appIP boundary matches the contract: generated output transfers to the client, the platform (studio + generator + primitives) remains ours.

13Verb Palette v1 — Draft for Review

The ~40 building blocks the BA snaps together on the flow canvas. Every verb is configured through dropdowns only (P1), declares its outcome branches explicitly (e.g. success / failure / pending), and is either generated behaviour or a wrapper over a dev-owned engine (§8). Anything not on this list is, by definition, a "request new verb" item.

CategoryVerbWhat it does · BA configures
Data & recordsrecord.createCreate a record · entity, field values (picked/mapped)
record.updateUpdate fields on a record · entity, record ref, field values
record.deleteSoft/hard delete · entity, record ref
record.findLook up records for later steps · entity, filter conditions
field.setSet a computed value on the current record · field, expression/source
counter.nextNext value from a numbering series (GST invoice no., order no.) · series
Status & flow controlstatus.transitionMove record to a new status — validated against its lifecycle (§5) · target status
branch.conditionIf/else on field values · condition builder (field, operator, value)
branch.decisionTableEvaluate a decision table (commission slab, eligibility) and branch/use outcome · table
wait.delayPause the flow · duration
wait.forEventPause until an external event (payment callback) · event, timeout branch
error.raiseStop with a business error · message template
flow.compensateReversal steps that run if a later step fails (ledger reversal on provider failure)
People & approvalsapproval.requestSend an approval task; branches approved / rejected · role, context screen
task.assignCreate a manual work item (KYC review queue) · role/queue, due rule
user.inviteCreate/invite a user · role, notify template
role.assignGrant/revoke a role · role
Wallet & money engine-backedwallet.checkBalanceBranches sufficient / insufficient · wallet, amount source
wallet.debitAtomic ledger debit · wallet, amount, narration template
wallet.creditAtomic ledger credit · wallet, amount, narration template
wallet.holdPlace a hold (pending txn) · wallet, amount
wallet.releaseRelease a hold · hold ref
wallet.reverseReverse an earlier entry · entry ref
commission.recordWrite a commission ledger entry (report-only per SOW) · decision table, parties
payment.collectCollect via payment gateway; branches paid / failed / pending · gateway, amount
payment.refundRefund a collection · payment ref, amount
payout.initiateQueue a settlement payout entry · beneficiary, amount source
Providers & external engine-backedprovider.callCall an upstream API via its adapter; branches success / failure / pending · provider, operation, field mapping
provider.checkStatusRe-query a transaction's status · txn ref
api.callGeneric REST call to a dev-registered endpoint · endpoint, mapping
webhook.emitNotify an external system · registered webhook, payload mapping
Communication & documentsnotify.sendSend via template · template, channel (SMS/email/push/in-app), recipient
otp.sendSend an OTP · channel, template
otp.verifyBranches valid / invalid / expired
document.generateRender a PDF from a template (invoice, statement, contract) · template, numbering series
document.requestUploadAsk a user to upload a document (KYC) · doc type, expiry rule
file.exportCSV/Excel export of a dataset · report/list definition
file.importBulk import with column mapping (catalog upload) · entity, mapping, error handling
Inventory & commerceinventory.reserveReserve stock for an order · warehouse rule, line items
inventory.releaseRelease a reservation · reservation ref
inventory.adjustStock adjustment with reason · item, quantity, reason list
Review-session agenda: walk each SRS module against this list and ask "can the BA express this flow with only these blocks?" Gaps become either a new verb (dev builds the primitive once) or a deliberate exclusion. Expect the palette to grow ~10% during the pilot — that is normal and healthy; uncontrolled growth beyond that signals verbs that are too low-level.