TT

toanle88/tally

Deployment & DevOps
0 stars Quality 45 Trend 8

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/v1 for the implemented identity, organization, COA, General Ledger, and workflow policy, request, decision, delegation, and escalation operations, plus anonymous GET /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


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

MIT

View this README on GitHub

Recommended Tools

Try a different keyword or remove a filter.

Install

npx skillfish add toanle88/tally