Documentation
¶
Overview ¶
Package factories generates the five-factory reconciliation demo: one application (database family "factory") run as seven SQLite databases, five production factories and two test copies, with a few deliberate, documented differences for `datatug reconcile` to find. Everything is deterministic and offline.
Index ¶
Constants ¶
const ( ProfileCountries = "reference-countries" ProfileCurrencies = "reference-currencies" ProfileProducts = "products" ProfileSettings = "factory-settings" )
Profile ids of the demo.
const ( MissingCurrency = "CHF" // factory-d-prod lacks it MissingCurrencyIn = "factory-d-prod" // RenamedCountry = "IE" // factory-e-prod names it "Eire" RenamedCountryIn = "factory-e-prod" // RenamedCountryName = "Eire" // DescribedSKU = "BEARING-608" // factory-c-prod describes it differently DescribedSKUIn = "factory-c-prod" // PricedSKU = "GEAR-20T" // factory-b-prod prices it differently (permitted) PricedSKUIn = "factory-b-prod" // TestSetting = "smtp_host" // factory-a-test differs from factory-a-prod TestSettingIn = "factory-a-test" // DriftColumn = "local_notes" // factory-e-prod has this extra products column DriftColumnIn = "factory-e-prod" // )
The deliberate differences, documented in the generated README.
const Catalog = "factory"
Catalog is the catalog id of the factory database in each environment.
const CheckID = "reference-data-agrees"
CheckID is the demo Check that reconciles the reference data.
const Family = "factory"
Family is the database family (DbModel) every factory database belongs to.
const README = `# Five-factory reconciliation demo
One application, database family ` + "`factory`" + `, runs as seven SQLite databases: five production
factories (` + "`factory-a-prod`" + ` … ` + "`factory-e-prod`" + `, kind production) and two test copies
(` + "`factory-a-test`" + `, ` + "`factory-b-test`" + `, kind test). Each environment has one catalog, ` + "`factory`" + `,
labelled with its tenant (` + "`factory-a`" + ` … ` + "`factory-e`" + `). Surrogate ids differ in every factory, so
rows align only by their semantic key.
## Deliberate differences
| Where | What | Kind of difference |
|---|---|---|
| factory-d-prod | currency ` + "`CHF`" + ` is missing | missing reference record |
| factory-e-prod | country ` + "`IE`" + ` is named "Eire" (others: "Ireland") | incorrect reference value |
| factory-c-prod | product ` + "`BEARING-608`" + ` has description "Ball bearing 608, sealed" | unexpected master-data value |
| factory-b-prod | product ` + "`GEAR-20T`" + ` costs 13.75 (others: 12.5) | permitted: price is instance-specific |
| factory-a-test | setting ` + "`smtp_host`" + ` is ` + "`smtp.test.factory-a.example`" + ` | environment-specific |
| factory-e-prod | ` + "`products`" + ` has an extra column ` + "`local_notes`" + ` | schema drift |
Stock levels differ in every factory; the products profile does not compare them (ignored), so the one permitted price difference stands out.
## Profiles and expected verdicts
| Profile | Command | Expected |
|---|---|---|
| reference-countries | ` + "`datatug reconcile --profile reference-countries`" + ` | discrepancies: IE unexpected, groups {a,b,c,d: Ireland} {e: Eire}, factory-e-prod deviating, no group authoritative (exit 1) |
| reference-currencies | ` + "`datatug reconcile --profile reference-currencies`" + ` | discrepancies: CHF missing in factory-d-prod (exit 1) |
| products | ` + "`datatug reconcile --profile products`" + ` | discrepancies: BEARING-608 description unexpected (factory-c-prod deviating); GEAR-20T price expected, factory-b-prod stays consistent; column ` + "`local_notes`" + ` missing in a–d (exit 1) |
| factory-settings | ` + "`datatug reconcile --profile factory-settings`" + ` | consistent: smtp_host differs as expected, baseline factory-a-prod (exit 0) |
The Check ` + "`reference-data-agrees`" + ` runs reference-countries and reference-currencies as reconcile
steps; it fails on the discrepancies above (` + "`datatug checks run reference-data-agrees`" + `, exit 1).
A factory that cannot be read makes its step inconclusive, never a pass.
Ad hoc: ` + "`datatug reconcile --query countries --key code --family factory --kind production`" + `.
## Data roles
` + "`datatug db roles suggest factory`" + ` classifies the tables from schema alone (countries and currencies
reference, products master, factory_settings configuration, orders and inventory_movements
transactional, audit_events event). Confirm one (` + "`datatug db roles confirm factory/countries`" + `) and
` + "`datatug reconcile --query countries --family factory --kind production`" + ` uses its rule without ` + "`--key`" + `.
## Running
Serve the project to an agent, then reconcile:
datatug serve --project <this folder> --allow-writes
datatug reconcile --profile reference-countries
--allow-writes is needed only to record Check runs (` + "`datatug checks run`" + `). The project has no access
policies, so the agent reads unrestricted; add a ` + "`policies/`" + ` folder and serve with --as/--role to
reconcile under Perimeter.
Reconcile is read-only: it never writes to a factory database.
## Refusing one factory
A local policy rule may name an ` + "`instance`" + ` (` + "`<environment>/<catalog>`" + `) or an ` + "`environment`" + `
kind. Put this in ` + "`policies/factories.yaml`" + ` and serve with ` + "`--as analyst`" + `:
apiVersion: dalgo.io/access/v1
kind: AccessPolicy
metadata: {name: factories}
default: deny
scopes:
- path: /countries
rules:
- {id: never-factory-e, effect: deny, operations: [query], instance: factory-e-prod/factory}
- {id: read-countries, effect: allow, operations: [query]}
` + "`datatug reconcile --profile reference-countries`" + ` then reports factory-e-prod as permission_denied and
the result as inconclusive, never consistent. The deny sits at the same scope as the allow so it wins;
a rule for another instance is left out of a read as if it were not there.
`
README documents the deliberate differences and the expected verdicts.
Variables ¶
var Instances = []Instance{ {Environment: "factory-a-prod", Tenant: "factory-a", Kind: datatug.EnvironmentKindProduction, /* contains filtered or unexported fields */}, {Environment: "factory-a-test", Tenant: "factory-a", Kind: datatug.EnvironmentKindTest, /* contains filtered or unexported fields */}, {Environment: "factory-b-prod", Tenant: "factory-b", Kind: datatug.EnvironmentKindProduction, /* contains filtered or unexported fields */}, {Environment: "factory-b-test", Tenant: "factory-b", Kind: datatug.EnvironmentKindTest, /* contains filtered or unexported fields */}, {Environment: "factory-c-prod", Tenant: "factory-c", Kind: datatug.EnvironmentKindProduction, /* contains filtered or unexported fields */}, {Environment: "factory-d-prod", Tenant: "factory-d", Kind: datatug.EnvironmentKindProduction, /* contains filtered or unexported fields */}, {Environment: "factory-e-prod", Tenant: "factory-e", Kind: datatug.EnvironmentKindProduction, /* contains filtered or unexported fields */}, }
Instances are the seven demo databases, in environment order.
var Queries = map[string]string{
"countries": "countries", "currencies": "currencies", "products": "products", "factory-settings": "factory_settings",
"orders": "orders", "inventory-movements": "inventory_movements", "audit-events": "audit_events",
}
Queries maps each saved query id to the table it reads.
Functions ¶
func Generate ¶
Generate writes the demo databases and project definitions into the project at dir through store: environments with their kinds, one catalog each with its tenant, the factory DbModel with its keys, saved queries, reconciliation profiles, the reference-data-agrees Check and a README. It overwrites what it wrote before.