A modern double-entry accounting application for managing ledgers, vouchers, invoices, inventory, taxes, financial reports, and business transactions.
Overview
A modern double-entry accounting application built as a Go modular monolith with a React frontend. The repository currently contains platform, identity/access, organization/master-data, COA, General Ledger, and workflow approval implementation slices; later finance capabilities and full release qualification remain planned. - Shared exact-decimal money, currency, accounting-scope, aggregate-version, authentication, idempotency, event-envelope, telemetry, database, and worker primitives under internal/platform/. - Identity and access services for users, roles, access policies, segregation rules, emergency access, authorization evidence, and durable PostgreSQL repositories under internal/identity/. - Organization and master-data services for legal entities, parties, customer profiles, vendor profiles, fiscal calendars, and approved master-data publication under internal/organization/.
README
Tally
A modern double-entry accounting application built as a Go modular monolith with a React frontend. The repository currently contains platform, identity/access, organization/master-data, COA, General Ledger, and workflow approval implementation slices; later finance capabilities and full release qualification remain planned.
Current Status
Implemented repository slices include:
- Shared exact-decimal money, currency, accounting-scope, aggregate-version,
authentication, idempotency, event-envelope, telemetry, database, and worker
primitives under
internal/platform/. - Identity and access services for users, roles, access policies,
segregation rules, emergency access, authorization evidence, and durable
PostgreSQL repositories under
internal/identity/. - Organization and master-data services for legal entities, parties, customer
profiles, vendor profiles, fiscal calendars, and approved master-data
publication under
internal/organization/. - COA segment definitions, values, combination validation, governed segment
changes, and approval-decision application under
internal/coa/. - General Ledger slices for ledgers, accounting books, charts of accounts,
accounts, posting, journal approval, reversal, posting barriers, soft close,
scoped reopen, and operational reopen/reclose under
internal/gl/. - Workflow policy maintenance, approval-request create/read, approval-decision
recording/exposure, delegation, and escalation implementation slices under
internal/workflow/, including effective-policy resolution, immutable subject and decision evidence, decision-time authorization, durable idempotency and PostgreSQL persistence, audit/outbox integration, authenticated APIs, and the WFA-SCR-02/WFA-SCR-04 workflow workspaces. Downstream decision application acknowledgement, notifications, production worker composition, and full qualification remain open. - A generated, authenticated API boundary under
/api/v1for the implemented identity, organization, COA, General Ledger, and workflow policy, request, decision, delegation, and escalation operations, plus anonymousGET /health/live. - A React/Vite frontend with shared finance interaction components and fixture-backed identity/access, master-data, COA, General Ledger, and workflow workspaces, including the WFA-SCR-02 decision view.
ROADMAP.md marks the EP-GL-001 and EP-WFA-001 parents locally complete by
explicit status override, while their child delivery items and PostgreSQL,
browser, accessibility, cross-context, notification, recovery, and release
qualification remain open. The current branch contains WFA User Stories 1–5
implementation slices without claiming downstream application acknowledgement,
production worker composition, or full workflow qualification.
For the business, technology, and architecture learning guide, see the TALLY docs site.
Verification Snapshot
The following commands were run locally on 2026-10-14:
GOCACHE=/tmp/tally-go-cache go test ./internal/identity ./internal/workflow ./internal/platform/httpapi ./cmd/api— passed.make sqlc-check— passed.GOCACHE=/tmp/tally-go-cache make api-generate-check— passed; OpenAPI validation and deterministic Go generation were verified.make api-ts-check— passed; deterministic TypeScript generation was verified.pnpm --dir web exec tsc --noEmit— passed.timeout 45s pnpm --dir web exec vitest run src/routes/route-registry.test.ts --pool=forks --maxWorkers=1 --fileParallelism=false— passed.pnpm --dir web build— passed.
The full frontend Vitest suite was attempted but interrupted after Vitest stalled during worker discovery, so it is not claimed as passed. PostgreSQL / Testcontainers persistence and release qualification were not run. These results are local evidence only; they do not claim hosted CI, live Entra, production audit, downstream decision application, performance/capacity, disaster recovery, or release qualification.
Prerequisites
- Go 1.26.3 or later
- Node.js 24 LTS or later
- pnpm 11.9.0 (
corepack enable pnpmornpm install -g [email protected]) - Docker Engine and Docker Compose v2
- Terraform
>= 1.8, < 2.0
Getting Started
# Install frontend dependencies
pnpm --dir web --ignore-workspace install --frozen-lockfile
# Configure local PostgreSQL before starting Compose
cp .env.example .env
# Start PostgreSQL (background, waits for health check)
make db-up
# Apply migrations, synthetic seed data, and verification
make db-prepare
# Start the API server (listens on :8080 or $HTTP_ADDR)
pnpm dev-api
# Start the frontend dev server (separate terminal)
pnpm dev-web
# Run the fast local checks (unit/component tests with bounded workers)
pnpm test:fast
Browser authentication configuration is separate: copy web/.env.example to
web/.env.local and set the VITE_* values for an interactive Entra run.
For a new local environment:
make verify-database-clean
Project Commands
Root package.json scripts
All commands must be run from the repository root.
| Command | Description |
|---|---|
pnpm build |
Build both API and web |
pnpm build:api |
go build ./cmd/api |
pnpm build:web |
tsc -b && vite build (via pnpm -C web run build) |
pnpm test |
Run all tests (API + web) |
pnpm test:fast |
Iterative API and frontend tests with bounded Vitest workers |
pnpm test:api |
go test ./... |
pnpm test:web |
vitest run (via pnpm -C web run test) |
pnpm test:web:fast |
Frontend Vitest with bounded worker/file parallelism |
pnpm test:slow |
Full tests, accessibility checks, persistence, and OpenAPI release gates; opt-in |
pnpm test:a11y |
Non-watch Playwright + axe checks for contrast, visual reflow, reduced motion, routed-shell semantics, and keyboard/focus behavior |
pnpm test:a11y:negative |
Controlled negative proof that an unlabeled button fails the axe assertion |
pnpm test:a11y:qualification |
Full or focused accessibility qualification rerun with target-to-evidence mapping |
pnpm docs:check |
Build the repository documentation site |
pnpm check |
pnpm run test && pnpm run build |
pnpm dev-api |
go run ./cmd/api |
pnpm dev-web |
vite dev server (via pnpm -C web run dev) |
Makefile targets — PostgreSQL lifecycle
| Target | Description |
|---|---|
make db-config |
Validate Docker Compose configuration |
make db-up |
Start PostgreSQL and wait for healthy status |
make db-wait |
Poll Docker health check up to 50 attempts, 1 s interval |
make db-status |
Show container status (docker compose ps postgres) |
make db-logs |
Show the latest PostgreSQL logs |
make db-shell |
Open psql against the configured local database |
make db-version |
Query SHOW server_version inside the container |
make db-down |
Stop the PostgreSQL container (preserves data volume) |
make db-migrate |
Apply all pending Goose migrations (bootstrap, platform, identity, organization, COA, GL, and workflow schemas) |
make db-seed |
Apply the committed synthetic seed data |
make db-verify |
Verify migration status and seed checksum |
make db-prepare |
Run db-migrate → db-seed → db-verify in order, stop on failure |
make db-reset |
Destroy and recreate the PostgreSQL volume from scratch |
make db-migrate-status |
Show applied and pending Goose migrations per schema |
make db-migrate-validate |
Validate migration ordering and Goose syntax without connecting |
make db-migrate-create |
Create a migration skeleton for bootstrap, platform, identity, organization, coa, gl, or workflow: make db-migrate-create SCHEMA=workflow NAME=desc |
make db-migrate-check |
Verify migration checksum inventory matches committed migrations |
make db-migrate-inventory |
Regenerate db/migrations/checksums.sha256 |
make db-sqlc-version |
Show the pinned sqlc version |
make db-sqlc-generate |
Regenerate typed Go query code from committed SQL source |
make db-sqlc-check |
Regenerate sqlc output, detect drift, and run Go tests |
make db-sqlc-integration |
Execute the sqlc platform seed-manifest integration test |
make persistence-tools-version |
Show pinned Goose and sqlc versions used by the release gate |
make sqlc-compile |
Parse and type-check committed sqlc schema and query source |
make sqlc-check |
Compare committed sqlc output with deterministic generated output |
make persistence-integration-test |
Run PostgreSQL 18 Testcontainers persistence integration tests |
make persistence-check |
Run the focused persistence drift gate used by CI |
make check-fast |
Fast migration/checksum validation and the default non-integration Go suite |
make check-slow |
Opt-in persistence and OpenAPI release gates; do not run automatically from an agent |
make api-generate |
Generate Go server interfaces and transport types from the OpenAPI contract |
make api-generate-check |
Validate deterministic Go generation, markers, compilation, and working-tree output |
make api-negative-check |
Run isolated negative checks for generated Go and TypeScript output |
make api-ts-generate |
Generate the TypeScript Fetch client and types from the OpenAPI contract |
make api-ts-check |
Validate deterministic TypeScript generation, inventory, markers, and frontend compilation |
make api-check |
Run the focused OpenAPI contract and generated-artifact drift gate |
make terraform-check |
Format, validate, and verify every Terraform root/profile plus credential-free drift and cost wrapper self-tests |
make terraform-environments-check |
Verify dev, demo, and prod-reference composition, profile safety, and focused Terraform tests |
make terraform-modules-check |
Validate the 11 reusable low-cost Terraform module contracts without credentials |
make terraform-tools-check |
Verify pinned Terraform, TFLint, Checkov, and Infracost versions |
make terraform-lint-check |
Run TFLint across Terraform roots and modules |
make terraform-security-check |
Run Checkov with the reviewed policy-exception manifest |
make terraform-security-check-docker |
Run the same pinned Checkov security gate through Docker Compose |
make terraform-plan-policy-check |
Run credential-free plan-policy fixture checks |
make terraform-pr-check |
Run the credential-free Terraform pull-request validation, policy, security, and repository contract gates |
make terraform-drift-check |
Run an authenticated refresh-only drift check for a selected environment |
make terraform-cost-check |
Compare an Infracost plan delta with the active-month cost review threshold |
make terraform-ci-check |
Verify OIDC subjects, protected apply workflow, credential-free PR workflow, and plan-summary hygiene |
| `make azure-learning-plan ENVIRONMENT=dev | demo` |
| `make azure-learning-apply ENVIRONMENT=dev | demo CONFIRM_APPLY=dev |
make azure-learning-deployment-check |
Run credential-free deployment-wrapper self-tests and shell validation |
ENVIRONMENT=dev make azure-learning-smoke |
Read-only smoke-test of deployment readiness and resource contracts |
make azure-learning-smoke-check |
Run credential-free smoke-runner safety and input tests |
make money-check |
Run focused exact-decimal money and currency primitive tests |
make accounting-scope-check |
Run focused accounting-scope identity and serialization tests |
make aggregate-version-check |
Run focused aggregate-version and boundary tests |
make shared-primitives-check |
Run the complete shared finance primitive serialization, boundary, ownership, and API representation gate |
make idempotency-check |
Run the contract-only idempotency concurrency, boundary, ownership, and API-preservation gate |
make idempotency-persistence-check |
Run idempotency migration, SQLC, PostgreSQL transaction, and concurrency integration checks |
make outbox-inbox-persistence-check |
Run outbox/inbox migration, SQLC, durability, constraint, and concurrent-claim checks |
make outbox-dispatch-check |
Run outbox lease, typed retry, fencing, and managed-exception checks |
make outbox-worker-check |
Run worker lifecycle, crash recovery, duplicate delivery, replay, migration, and SQLC checks |
make check |
Run migration validation, checksum check, and go test ./... |
make ci-check |
Verify the aggregate pull-request workflow contract and repository artifact safety |
make repository-integrity-check |
Reject forbidden local, Terraform, dependency, and build artifacts |
make verify-database |
Run end-to-end database verification from current state |
make verify-database-clean |
Delete volume, recreate, and run full verification from scratch |
Local PostgreSQL
A single PostgreSQL 18.4 (bookworm) development container is defined in
compose.yaml with a database-aware health check.
- Bound to
127.0.0.1:5432(localhost only). - Data persists across restarts via a named volume.
- Configured through environment variables in
.env. - For local learning and development only — no production availability, backup, recovery, or security qualification claim.
Persistence Verification
The focused persistence release gate is:
make persistence-check
The focused DLV-PLAT-007 User Story 2 gate is:
make outbox-inbox-persistence-check
It verifies the durable integration.outbox and integration.inbox migration,
platform-owned sqlc queries, PostgreSQL constraint behavior, commit/reopen
durability, rollback, reconciliation lookup, and concurrent due-row claims.
The focused DLV-PLAT-007 User Story 3 gate is:
make transactional-coordination-check
It verifies the platform transaction coordinator, atomic source publication, atomic consumer effects and resulting publications, duplicate established-result handling, identity-content conflicts, failed inbox evidence, reconciliation, sqlc drift, package ownership, and PostgreSQL integration behavior.
The focused DLV-PLAT-007 User Story 4 gate is:
make outbox-dispatch-check
It verifies lease renewal, owner-fenced establishment and rescheduling, typed retry delays, retry exhaustion, managed-exception retention, SQLC and migration drift, package ownership, and PostgreSQL integration behavior.
It verifies the repository-pinned Goose and sqlc tools, validates Goose
migration sets, checks db/migrations/checksums.sha256, compiles sqlc source,
detects stale or manually edited generated sqlc output, runs Go tests, and then
runs the PostgreSQL 18 Testcontainers persistence integration tests.
The focused DLV-PLAT-007 User Story 5 gate is:
make outbox-worker-check
It verifies worker lifecycle, independent admission budgets, dispatcher polling, crash/restart recovery, duplicate and ordering behavior, generation- scoped replay, immutable outbox event facts, migration upgrade/down behavior, SQLC drift, package ownership, and PostgreSQL integration evidence.
Author SQL in db/queries/ and regenerate committed output with
make db-sqlc-generate. Generated files under
internal/platform/database/platformdb/ are machine-produced and must not be
manually edited. Author migrations under the owning schema directory in
db/migrations/, update the checksum inventory with
make db-migrate-inventory, and verify drift with make db-migrate-check.
Shared-environment migration correction is forward-fix by default. Destructive
reset commands such as make db-reset and make verify-database-clean are for
disposable local development state only.
OpenAPI Artifacts
The OpenAPI source under contracts/openapi/ is bundled with the pinned Redocly
CLI before generation. ogen v1.23.0 is pinned as a Go tool dependency and
generates server interfaces and transport types into
internal/platform/httpapi/generated/. Generated files are machine-produced
and must not be edited manually.
Use make api-generate to regenerate output and
make api-generate-check to validate deterministic output, generated markers,
the expected artifact inventory, OpenAPI validation, and Go compilation. Use
make api-negative-check for isolated intentional failure checks, and
make api-check for the complete clean positive gate used by focused CI.
TypeScript client generation bundles the same OpenAPI source and uses the
pinned @hey-api/openapi-ts 0.99.0 tool. It writes machine-produced output to
web/src/generated/api/; use make api-ts-generate to regenerate it and
make api-ts-check to validate deterministic output, the generated inventory,
the bundled Fetch client, and temporary TypeScript compilation. The wrapper is
the supported entry point because it supplies a temporary bundled OpenAPI
input; direct config execution expects the ignored fallback bundle at
contracts/openapi/dist/openapi.bundle.yaml. make api-check compares both
committed generated directories with fresh output and fails on stale, missing,
deleted, or extra artifacts. make api-negative-check demonstrates those
failures in temporary copies.
The GitHub Actions workflow at .github/workflows/openapi.yml invokes
make api-check after frozen root and frontend dependency installation. This
is focused DLV-PLAT-004 drift detection. The aggregate
.github/workflows/pull-request-quality.yml invokes the same gate as part of
the required Pull-request quality / required pull-request status check.
Pull-request CI Quality Pipeline
.github/workflows/pull-request-quality.yml is the repository-owned aggregate
pull-request gate for DLV-CI-001. It runs Go and frontend tests/builds,
automated accessibility checks, OpenAPI/generated-artifact verification,
PostgreSQL 18 Testcontainers persistence verification, credential-free
Terraform validation and policy checks, repository integrity and security
scanning, and the documentation build.
The workflow uses only read-only repository permissions and does not log in to
Azure, access remote Terraform state, apply or destroy infrastructure, run
authenticated drift checks, or publish raw plans, state, secrets, or provider
errors. The six quality jobs fan into the stable
Pull-request quality / required job, which fails when any dependency fails,
is cancelled, or is skipped.
Focused OpenAPI, persistence, Terraform, and documentation workflows remain available for push/manual verification but no longer create duplicate pull-request checks. Actual GitHub branch-protection configuration is external repository state and is not claimed by this workflow change.
Terraform and Protected Remote State
The Terraform boundary is established under infra/terraform/ with separate
bootstrap and dev, demo, and prod-reference roots. Each root pins the
approved Terraform and provider constraints and carries its own reviewed
.terraform.lock.hcl file.
The bootstrap root owns the dedicated Azure Blob state resource group, storage
account, private state containers, per-environment state identities, and
container-scoped Blob Data Contributor assignments. Bootstrap, dev, demo,
and prod-reference use distinct state keys; Terraform workspaces are not the
isolation boundary.
Run the focused local gate with:
make terraform-check
User Story 5 plan-policy, budget, drift, cost, and external-evidence boundaries
are recorded in
docs/verification/DLV-IAC-001-us5-plan-policy-drift-cost.md.
User Story 7 adds credential-free PR Terraform validation and policy checks and a manually
dispatched, main-only protected apply workflow using Azure OIDC. Its
repository evidence and external GitHub/Azure setup checklist are recorded in
docs/verification/DLV-IAC-002-us7-ci-oidc-federation.md.
The gate initializes providers with -backend=false, then runs formatting,
validation, bootstrap and environment contract checks, state-key checks,
security assertions, focused root tests, and forbidden-artifact checks for every
root. It does not require Azure
credentials, access an Azure subscription, create resources, or configure
remote state. See the User Story 2 verification record
for the two-phase bootstrap and recovery procedure.
Optional Azure learning deployment
Azure is optional; local development does not depend on it. The learning
deployment accepts only dev or disposable demo and authenticates through
the Azure CLI. Set the required ARM_*, TF_STATE_*, and TF_VAR_*
environment variables externally, including a sensitive PostgreSQL password.
Do not create or commit .tfvars, state, plan, or credential files.
The apply workflow first creates the resource group and ACR, imports the
externally supplied API and worker images by immutable digest, then runs the
full Terraform plan and apply. Source images must be supplied through
AZURE_API_SOURCE_IMAGE and AZURE_WORKER_SOURCE_IMAGE; no image build or
frontend content deployment is included yet.
Apply also requires AZURE_LEARNING_ESTIMATED_MONTHLY_COST_USD, an
operator-supplied non-negative estimate. The estimate is printed as
unverified context before the final interactive confirmation; it is not an
Azure billing quote.
make azure-learning-plan ENVIRONMENT=demo
CONFIRM_APPLY=demo make azure-learning-apply ENVIRONMENT=demo
The apply command requires confirmation before the foundation apply and pauses again after the complete Terraform plan, requiring the operator to type the selected environment name again. These are the explicit review gates for the resource and cost impact before either apply.
Disposable environments have a separate guarded destroy command. It accepts
only the selected dev or demo state, requires
CONFIRM_DESTROY= before Azure or Terraform remote-state access,
prints a value-free resource-address destroy summary, and requires the
environment name again before proceeding. If PostgreSQL remains in the
selected state, it creates and verifies a uniquely named Azure-managed
on-demand backup before applying the exact temporary destroy plan.
CONFIRM_DESTROY=demo make azure-learning-destroy ENVIRONMENT=demo
make azure-learning-destroy-check
The command verifies the selected subscription, environment profile, resource
group, PostgreSQL identity, empty post-destroy state, resource-group absence,
and a follow-up remote-state lock operation. It never uses az group delete,
manual lock deletion, force-unlock, bootstrap state, or Docker, and a demo
destroy cannot implicitly touch dev. Destroy reports are redacted and
written to artifacts/deployment-destroy/.json; temporary
plans, logs, and backup metadata are removed on exit. The Azure CLI reference
exposes the backup option as --name, while Microsoft’s how-to page currently
shows --backup-name; the command checks the installed CLI help and fails
closed if --name is unavailable.
The command prints only non-sensitive resource outputs and checks the existing
API GET /health/live endpoint. It does not run migrations or seed finance
data. The approved deployment specification also names /health/ready, but
the current API does not implement it; the learning profile therefore uses
/health/live for both Container Apps probes until the owning API/platform
delivery adds a distinct readiness contract. This apply procedure is not production
qualification, CI federation, smoke-test qualification, destroy, or recovery
evidence.
User Story 10 documents the supported recovery paths for state locks, drift,
failed apply/destroy, identity rotation, resource-group recovery, and
backup/restore evidence in
docs/verification/DLV-IAC-002-us10-recover-state-and-document-operations.md.
The runbook preserves Terraform ownership, keeps bootstrap state separate, and
does not claim authenticated Azure recovery or production qualification.
EP-IAC-001 is closed by owner decision; remaining live Azure qualification and
optional external exercises are explicitly deferred for this project.
The wrapper uses the authenticated Azure CLI operator for this learning workflow. Per-environment state identities are provisioned by the bootstrap root, but matching identity authentication remains unverified. Because EP-IAC-001 is closed by owner decision, no further live identity qualification is planned; the wrapper claims separate state keys and containers, not completion of that identity criterion.
Deployment smoke evidence
After an approved dev or disposable demo apply, run:
ENVIRONMENT=dev make azure-learning-smoke
This read-only command distinguishes “Terraform applied” from “environment
usable.” It checks the selected state outputs, Azure resources and provisioning
states, HTTPS certificate validation and GET /health/live, immutable image
digests and ACR manifests, managed identity role assignments, and monitoring
diagnostics. It checks Static Web App resource existence only; Story 6 does not
deploy frontend content. It never runs plan/apply/destroy, migrations, seeds,
or finance writes. The redacted report is written to
artifacts/deployment-smoke/.json and records cleanup as
not-run because destruction belongs to User Story 9.
The report is smoke evidence, not production or release qualification. Database
migration evidence is separately owned and therefore remains
not-verified/blocked unless an approved release step supplies evidence; local
make db-migrate is not Azure release evidence. Reports must remain redacted:
never add passwords, tokens, connection strings, Terraform state, or raw Azure
CLI error payloads. Resource IDs and immutable image digests are the intended
non-secret evidence.
Architecture
The DLV-UX-002 User Story 3 screen-reader/browser matrix, semantic review
procedure, and synthetic finding trace are recorded in
docs/verification/DLV-UX-002-us3-screen-reader-semantic-review.md.
Repository semantic proxy coverage is implemented; witnessed NVDA and
VoiceOver sessions remain pending and are not represented as passed evidence.
The User Story 4 visual adaptability, contrast, reflow, and reduced-motion
automated baseline is recorded in
docs/verification/DLV-UX-002-us4-visual-adaptability-motion.md.
The User Story 5 qualification report template, requirement traceability,
defect decisions, retest example, and focused rerun targets are recorded in
docs/verification/DLV-UX-002-us5-accessibility-qualification-evidence.md.
Tally uses a modular-monolith architecture: a single deployable Go
application with enforced bounded-context module boundaries under
internal/, and a React single-page application frontend. The architecture
is specified in docs/specs/system_design/.
The technology baseline (from the approved solution architecture):
| Area | Current | Planned |
|---|---|---|
| Backend | Go 1.26.3 + chi/v5 5.3.1; generated API boundary, liveness endpoint, and runtime wiring for identity, organization, COA, General Ledger, and workflow policy/request/decision services | Remaining bounded-context modules and finance capability handlers |
| Frontend | React 19, TypeScript, Vite, Tailwind CSS 4, daisyUI 5, shared semantic UI primitives, routed shell, fixture-backed scope context, operational route seams, record-context/lifecycle/money/evidence/privacy wrappers, TanStack Table-backed operational worklist/process fixtures, and identity/access, master-data, COA, General Ledger, and workflow workspaces including WFA-SCR-02 decision exposure | Later capability screens and full qualification |
| Package manager | pnpm 11.9.0 | — |
| Database | PostgreSQL 18 Docker Compose dev service, Goose migrations, pgx/v5 connection pool, sqlc-generated platform, identity, organization, COA, GL, and workflow queries including decision evidence, synthetic seed/verify scripts, migration checksum inventory, focused persistence drift command and aggregate PR quality workflow | Later bounded-context schemas and release qualification |
| Styling | Tailwind CSS 4 as the primary styling/layout system with daisyUI 5 theme and wrapper support | — |
| Client state | — | TanStack Query |
| API contract | OpenAPI 3.1 source with generated Go and TypeScript artifacts; runtime exposes GET /health/live and authenticated /api/v1 operations for implemented identity, organization, COA, General Ledger, and workflow policy/request/decision slices |
Future capability operations and full contract qualification |
| Infrastructure | Terraform provider contract, per-root lockfiles, protected Blob remote-state bootstrap, isolated state keys and identities, reusable low-cost module contracts, dev/demo/prod-reference profile composition, and optional dev/demo deployment wrapper | Deferred: live Azure apply evidence and production qualification |
| CI/CD | Aggregate pull-request quality workflow with focused push/manual verification workflows | Protected deployment and release qualification |
Current Repository Structure
The tree below shows the maintained source boundaries and representative
artifacts. Generated files are committed where the repository contract requires
them; the complete inventory is available through git ls-files.
.
├── cmd/
│ ├── api/
│ │ └── main.go # Go API entry point, graceful shutdown
│ └── worker/
│ └── main.go # Safe worker composition scaffold
├── contracts/
│ └── openapi/ # OpenAPI 3.1 source and generated-contract inputs
├── db/
│ ├── migrations/
│ │ ├── bootstrap/ # platform, identity, organization, COA, GL, workflow schemas
│ │ ├── platform/ # idempotency, outbox/inbox, seed manifest
│ │ ├── identity/ # identity/access persistence
│ │ ├── organization/ # OMD persistence
│ │ ├── coa/ # segment and change-request persistence
│ │ ├── gl/ # ledger, posting, and gate persistence
│ │ └── workflow/ # policy, request, and decision persistence
│ ├── checksums.sha256 # Migration integrity checksums
│ ├── queries/
│ │ ├── platform/ # outbox/inbox and seed queries
│ │ ├── identity/ # identity/access queries
│ │ ├── organization/ # organization queries
│ │ ├── coa/ # COA queries
│ │ ├── gl/ # General Ledger queries
│ │ └── workflow/ # workflow and approval queries
│ └── seeds/
│ └── local/
│ └── v1.sql # Synthetic seed data
├── infra/
│ └── terraform/
│ ├── bootstrap/ # Protected remote-state bootstrap root
│ ├── modules/ # DLV-IAC-001 US3 reusable leaf modules
│ └── environments/
│ ├── dev/ # Learning environment root
│ ├── demo/ # Disposable environment root
│ └── prod-reference/ # Production topology reference root
├── internal/
│ ├── coa/
│ │ ├── segment_definition.go # Segment definition domain/service
│ │ ├── segment_value_service.go # Segment value maintenance
│ │ ├── segment_change_request.go # Governed change requests
│ │ ├── segment_change_approval.go # Approval decision application
│ │ └── coadb/ # sqlc-generated COA query package
│ ├── gl/ # Ledgers, posting, reversal, and posting gates
│ ├── identity/ # Identity, access, segregation, emergency access
│ ├── organization/ # Legal entities, parties, profiles, calendars, publication
│ ├── workflow/ # Approval policies, requests, decisions, and ports
│ └── platform/
│ ├── aggregateversion/ # Optimistic-concurrency primitive
│ ├── authentication/ # OIDC/JWT authentication middleware
│ ├── events/ # Event envelope and versioning
│ ├── idempotency/ # Request fingerprint and durable idempotency
│ ├── money/ # Exact-decimal money and currency primitives
│ ├── accountingscope/ # Explicit accounting scope
│ ├── database/ # pgx pool, migrations, sqlc, integration tests
│ ├── httpapi/ # Generated API boundary and handlers
│ ├── httpx/ # Health endpoint
│ ├── integration/ # Transactional outbox/inbox coordination
│ ├── telemetry/ # Logs, traces, and bounded metrics
│ └── worker/ # Worker lifecycle and admission host
├── scripts/
│ ├── README.md # Script documentation
│ ├── openapi/
│ │ ├── api-check.sh # Aggregate contract and artifact drift gate
│ │ ├── api-generate-check.sh # Working-tree-safe Go generation check
│ │ ├── expected-go-artifacts.txt # Generated Go artifact inventory
│ │ ├── expected-typescript-artifacts.txt # Generated TypeScript inventory
│ │ ├── go-generate.sh # Pinned ogen generation wrapper
│ │ ├── go-negative-check.sh # Go negative generation checks
│ │ ├── typescript-generate.sh # Bundled OpenAPI TypeScript generation
│ │ ├── typescript-client-check.sh # TypeScript generation, drift, and compile check
│ │ └── typescript-negative-check.sh # TypeScript negative generation checks
│ ├── db/
│ │ ├── migrate.sh # Goose migration runner
│ │ ├── sqlc-check.sh # sqlc generation drift check
│ │ ├── seed.sh # Seed applier with checksum guard
│ │ └── verify.sh # Migration status + seed checksum verification
│ ├── tools/
│ │ └── sqlc.sh # Pinned sqlc launcher
│ └── verify/
│ ├── ci-contract.js # Aggregate CI workflow contract verification
│ ├── accounting-scope.sh # Accounting-scope verification
│ ├── aggregate-version.sh # Aggregate-version verification
│ ├── database.sh # End-to-end database verification workflow
│ ├── event-envelope.sh # Event-envelope contract verification
│ ├── idempotency-persistence.sh # Durable idempotency verification
│ ├── idempotency.sh # Idempotency contract verification
│ ├── money.sh # Focused money primitive verification
│ ├── openapi-story1.sh # OpenAPI foundation verification
│ ├── outbox-dispatch.sh # Outbox dispatcher verification
│ ├── outbox-worker.sh # Worker lifecycle and replay verification
│ ├── outbox-inbox-persistence.sh # Outbox/inbox persistence verification
│ ├── request-fingerprint.sh # Request fingerprint verification
│ ├── repository-integrity.sh # Forbidden-artifact and workflow safety checks
│ ├── shared-primitives.sh # Shared primitive verification
│ ├── terraform.sh # Terraform boundary verification
│ ├── terraform-environments.sh # Environment profile verification
│ └── transactional-coordination.sh # Transactional coordination verification
├── web/
│ ├── src/
│ │ ├── app/
│ │ │ ├── app.tsx # Router and fixture-backed app composition
│ │ │ ├── development-examples.tsx # Reusable foundation and operational examples
│ │ │ ├── operational-example.tsx # Worklist and process component composition
│ │ │ ├── operational-fixtures.ts # Synthetic operational component fixtures
│ │ │ ├── record-detail-example.tsx # Synthetic record-detail composition
│ │ │ ├── record-detail-fixtures.ts # Typed record-context fixtures
│ │ │ ├── app-shell.tsx # Responsive presentational shell
│ │ │ ├── workflow-approval-workspace.tsx # WFA worklist/detail/create/decision slice
│ │ │ └── app.test.tsx # Shell region and theme tests
│ │ ├── components/accounting-scope-selector/ # Persistent scope context
│ │ ├── components/record-context/ # Shared record-context types
│ │ ├── components/operational-context/ # Shared operational presentation types
│ │ ├── components/worklist-and-saved-filters/ # TanStack Table worklist
│ │ ├── components/state-aware-action-bar/ # Permitted and blocked actions
│ │ ├── components/settlement-and-reconciliation-panel/ # Supplied balances and states
│ │ ├── components/exception-resolution-panel/ # Evidence and authorized resolutions
│ │ ├── components/result-lookup/ # Established result outcomes
│ │ ├── components/process-progress-panel/ # Cross-capability progress
│ │ ├── components/record-identity-header/ # Record identity and ownership
│ │ ├── components/lifecycle-timeline/ # Chronological state transitions
│ │ ├── components/money-and-currency-panel/ # Typed money roles and evidence
│ │ ├── components/correction-lineage-panel/ # Immutable correction lineage
│ │ ├── components/evidence-drawer/ # Access-controlled evidence links
│ │ ├── components/sensitive-data-guard/ # Masked sensitive values
│ │ ├── components/legal-hold-indicator/ # Retention/legal-hold state
│ │ ├── components/ui/ # Typed shared UI primitives
│ │ │ └── ui.test.tsx # Primitive semantics tests
│ │ ├── lib/auth/ # Authentication/scope adapter seam
│ │ ├── lib/scope/ # In-memory scope context and stale guards
│ │ ├── routes/ # Typed route registry and React Router setup
│ │ ├── main.tsx # React entry point
│ │ ├── index.css # Tailwind/daisyUI CSS-first foundation
│ │ └── test/
│ │ └── setup.ts # jest-dom and Testing Library cleanup
│ ├── public/
│ │ └── favicon.svg
│ ├── index.html
│ ├── vite.config.ts
│ ├── tsconfig.json
│ ├── tsconfig.app.json
│ ├── tsconfig.node.json
│ ├── eslint.config.js
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── .gitignore
│ └── README.md # Vite scaffold notice (unused)
├── docs/
│ ├── backlog/ # Epic and delivery-item user stories
│ │ ├── epic-template.md
│ │ ├── milestone-template.md
│ │ ├── story-template.md
│ │ └── stories/ # Platform, UX, IAC, OPS, IAM, OMD, COA, GL, WFA plans
│ ├── specs/ # PRD, domain model, UX, NFR,
│ │ # system design, technical specs
│ └── verification/ # Clean-clone and reproducibility evidence
│ ├── DLV-PLAT-001_clean_clone_evidence.md
│ ├── DLV-PLAT-002_local-db-reproducibility.md
│ ├── DLV-PLAT-003-persistence.md
│ ├── DLV-PLAT-004-go-api-artifacts.md
│ ├── DLV-PLAT-004-contract-drift.md
│ ├── DLV-PLAT-004-typescript-client.md
│ ├── DLV-PLAT-005-shared-primitives.md
│ ├── DLV-PLAT-006-durable-coordination-verification.md
│ ├── DLV-PLAT-007-event-envelope.md
│ ├── DLV-PLAT-007-outbox-dispatch.md
│ ├── DLV-PLAT-007-outbox-inbox-persistence.md
│ ├── DLV-PLAT-007-transactional-coordination.md
│ └── DLV-PLAT-007-worker-lifecycle-replay.md
├── .agents/
│ ├── commands/
│ │ ├── review-branch-diff.md
│ │ └── update-readme.md
│ └── skills/
│ ├── create-pr/
│ │ └── SKILL.md
│ ├── review-current-branch-diff/
│ │ └── SKILL.md
│ └── update-readme/
│ └── SKILL.md
├── .env.example # Developer PostgreSQL config template
├── .gitattributes
├── .gitignore
├── compose.yaml # PostgreSQL 18.4 dev service + health check
├── Makefile # PostgreSQL lifecycle + migration targets
├── package.json # Root scripts ([email protected])
├── pnpm-lock.yaml
├── sqlc.yaml # sqlc code-generation configuration
├── go.mod # Go 1.26.3, chi/v5 5.3.1, goose/v3 3.27.1
├── go.sum
├── AGENTS.md
├── ROADMAP.md
├── LICENSE # MIT
└── README.md
Planned Target Architecture
The approved architecture defines 19 bounded-context modules under
internal/, each following a consistent structure (planned):
internal//
├── domain/ # aggregates, value objects, policies, domain events
├── application/ # commands, queries, coordinators, transaction scripts
├── ports/ # repository, clock, authorization interfaces
└── adapters/ # postgres, HTTP mapping, integration-event mapping
The planned modules are: organization, gl, ap, ar, payroll,
invoicing, payments, reporting, intercompany, revenue,
fixedassets, multicurrency, fiscalperiod, coa, bankfeeds, tax,
workflow, identity, audit. Capability delivery remains incremental.
The current repository contains implementation slices under internal/identity,
internal/organization, internal/coa, internal/gl, and internal/workflow.
The COA slice covers segment definitions, values, combination validation,
governed changes, and approval-decision application. The GL slice covers
posting and ledger-control behavior, while the workflow slice covers policy
maintenance, approval-request creation/read evidence, and User Story 3
decision recording/exposure. Downstream decision application acknowledgement,
the full delegation/escalation lifecycle, the remaining planned modules, and
full capability-level qualification are not delivered by these slices.
The target module layout above remains planned. Current slices use the repository’s existing package boundaries and adapters; they are not evidence that every future module has already been created in the target layout.
Cross-module rules (from the approved design):
- Domain packages import only the Go standard library.
- No module imports another module’s repository or adapter.
- Cross-module calls use a published application interface or integration event.
- Each module owns its PostgreSQL schema.
Finance Rules
TALLY enforces these design rules across all modules:
- Never use binary floating point for money.
- Posted or established financial records are immutable.
- Correct established facts through reversal, adjustment, amendment, return, unapplication, replacement, or compensation.
- Retriable state-changing operations require idempotency.
- Integration events use the transactional outbox.
- Material state changes require authorization and audit evidence.
- Modules must not directly access another module’s adapter or owned schema.
- Shared technical packages must not contain capability-specific finance rules.
- Avoid unnecessary abstractions and dependencies.
Roadmap
See ROADMAP.md for the full delivery plan spanning M0
(engineering foundation) through M9 (full-system qualification). The current
platform backlog has completed DLV-PLAT-001 through DLV-PLAT-007; DLV-PLAT-007
has its envelope, persistence, transactional-coordination, dispatch, worker
lifecycle, crash recovery, ordering, and replay foundations implemented.
Semantic payload safety is tracked as a separate deferred follow-up. The
roadmap also records local/owner-closed foundation slices for EP-OPS-001,
EP-IAM-001, EP-OMD-001, and EP-COA-001; each closure retains explicit
deferred qualification boundaries.
EP-GL-001 and EP-WFA-001 are marked locally complete by the explicit status
overrides recorded in ROADMAP.md; their implementations are present in the
current source tree, but the child delivery items and qualification follow-ups
remain open. The current branch contains WFA User Stories 1–5 implementation
slices. Downstream decision application acknowledgement, production worker
composition, notifications, and full workflow qualification remain future
scope. Focused gates
include make shared-primitives-check, make outbox-dispatch-check,
make outbox-worker-check, and make api-check; the verification snapshot
above records the commands actually run for this README update.
The optional Terraform and Azure learning-environment epic, EP-IAC-001, is
closed by owner decision; remaining live Azure qualification and optional
external exercises are explicitly deferred for this project.
License
Recommended Tools
Try a different keyword or remove a filter.
Install
npx skillfish add toanle88/tally