The project manifest

Every layer so far describes the application. The infrastructure layer describes what the application is built and run against — and it lives in one file: project.vishwakarma, the project manifest. It is the only place project-wide configuration lives; everything else in the workspace is domain, application, presentation, or overlay.

project.vishwakarma
project chowk {
  framework "v0.7.0"
  module    "github.com/BhumikaAI/chowk"
  backend   go
  orm       chitragupt

  datastore chowk_db {
    url        "${DATABASE_URL}"
    sys_url    "${DATABASE_SYS_URL}"
    migrations "migrations"
  }

  // … plugin slots and client realms …
}

The core settings

The top of the manifest fixes the generation target:

SettingWhat it does
framework "<version>"The framework release the app is generated and built against. Changing it moves the whole app to a new framework version — the one dial that re-derives everything below.
module "<path>"The Go module path the generated backend uses.
backend goThe backend language/runtime the code generator emits.
orm chitraguptThe persistence layer — the ORM that maps aggregates to tables and runs migrations.

These aren't wired by hand anywhere else; the generator reads them here and emits a go.mod pinned to the framework, a runtime, and the whole dependency closure.

datastore — the application database

The datastore block names the database the application persists to and how migrations reach it:

project.vishwakarma
datastore chowk_db {
  url        "${DATABASE_URL}"
  sys_url    "${DATABASE_SYS_URL}"
  migrations "migrations"
}
  • url — the application connection string, used on the request path as the app role (the least-privileged role that RLS policies are written against). ${DATABASE_URL} is env-expanded at runtime, so the same manifest runs against dev, staging, and prod databases.
  • sys_url — an elevated connection used for DDL and migrations (a superuser). Declaring it is what tells the migration tooling a distinct system pool exists; the two-pool split keeps request-path queries off the privileged role.
  • migrations — where the ORM writes the migration it derives.

Each sub-domain then binds to this datastore (data_store { name "chowk_db" engine postgres } in its declaration file), which is what makes its aggregates materialize as tables. A sub-domain that forgets to bind is silently skipped by the migration diff — so the binding is load-bearing.

Migrations are derived, not written

Worth stating plainly because it surprises people: you never hand-write a migration. The ORM diffs the desired schema — derived from your entities — against the live database and generates the delta. Add a field to an aggregate, and the migration to add the column is computed for you at deploy time. The manifest's job is only to say which database and which roles; the schema itself comes from the domain layer.

What else lives here

The manifest also carries the plugin slots (the event bus, cache, and observability substrate) and the client realms (the generated web and CLI SDKs). Those are the subject of Plugin slots & the process tree — the runtime substrate the app plugs into.