Solynth Network · solynth.net

Strawman Architecture · For analysis and refinement

Governed State: a metadata-driven version control and upgrade system for the application platform

A declarative, desired-state approach to versioning code, schema, seed data, configuration and infrastructure as one governed lineage, with a deterministic reconciliation substrate beneath an AI-assisted upgrade campaign.

Author  Robert Harvey Curtis (rhc)
Status  Strawman · circulated for critique, not yet a build specification
Revision  0.1 · August 2026

This note draws together a design worked out from two directions at once. From below, as tooling for the update, upgrade and migrate process; from above, as the orchestration that governs a whole release campaign. The two meet in the middle, and this document is the record of where they meet. It is deliberately a strawman: comprehensive enough to be argued with, promoted, and added to, but not yet settled enough to build from without further decisions, which are listed plainly at the end.

The lineage is honest and worth stating up front. The pattern is a generalisation of what the Lawson System Foundation and the later Landmark architecture do for their own world, reworked to be language-agnostic, to govern more than a database, and to design out the failure modes that leave those systems out of sync and repaired by hand. Where this document describes how those systems work internally, it rests on the author's direct and long-standing experience of them rather than on independently verified vendor documentation; the epistemic status of every class of claim is set out in the closing note, and readers extending this body of knowledge should observe that boundary.

01 The first principle

Declarative desired state, and the two properties that make it safe

The core is not a migration engine. It is a reconciliation engine: it holds a description of the state the system should be in, reads the state the system is actually in, computes the difference, and applies whatever is necessary to close it. This is the same shape found in desired-state configuration generally, in infrastructure reconcilers that compute a plan against a target and then apply it, and in the database-DevOps distinction between state-based and migration-based tooling. The dictionary-of-what-is compared against a dictionary-of-what-should-be is squarely the state-based model, and folding default values and seed rows into that dictionary carries it a step further than most schema tools, which stop at structure and leave reference data to drift.

Two properties decide whether such an engine is safe, and the whole rest of the design is really a discipline for preserving them. The first is confluence: the order and route of operations do not change the resting state. The second is idempotence: arriving twice looks identical to arriving once. Declarative desired state hands both to you for free on structure, because an assertion such as column B exists, integer, not null is absolute. Run it from any starting point, by any road, and the column ends identical.

The governing metaphor All roads lead to Rome. For structure, they lead not merely to Rome but to the same Rome, furnished the same way, however many times the trip is made. The engineering problem is the set of cases where that is not automatically true, and the design is the machinery that forces those cases back into line.

The value of the design lies precisely in refusing to pretend that everything is confluent. Structure is; a large part of the data is; but some operations are path-dependent, some are irreversible, and some cannot be inferred from the end states at all. Naming those cases exactly, and handling each on its own terms, is what separates a system that can be trusted at go-live from one that is plausible until it corrupts a customer's data three weeks later.

02 The object model

A generic kernel over typed objects and providers

The engine should not be a database tool that can also move files. It should be a reconciliation kernel over a typed object graph, in which a table, an index, a full-text index, a stored function, a compiled programme, a source file in any language, a SQL script, a configuration value, a seed row and an infrastructure resource are all simply objects of different type. Each object carries four things: a type, a stable identity, a desired-state descriptor, and a reference to a provider for that type.

A provider knows how to do exactly three things: read the actual state of an object of its type, compute the delta between actual and desired, and apply that delta. The kernel stays wholly generic. It walks the object graph, asks each provider to plan, orders the resulting operations by dependency, and applies them. The database-reorganisation step then stops being a special programme and becomes the kernel invoked over the subset of objects whose type happens to be database. Adding a new capability means writing a new provider, not touching the engine, which is what lets the design scale past what can currently be enumerated.

This is the layer that stays language-agnostic on purpose. The platform has to govern COBOL, fourth-generation sources, JavaScript, SQL and configuration sitting in directory structures, and cannot demand that they all be rewritten into one language. Generality is bought here, and the price of that generality is paid, and contained, in the sections that follow.

03 Operations

The operation taxonomy, and why the end state is not enough

Whether a change is confluent depends on how its outcome is specified, and this yields three categories that the system must treat differently.

Absolute assertions keyed by identity

When the desired state says that the row keyed K holds value V, the outcome is a function of identity, not of the prior value. Every road reaches the same Rome and Rome holds the same furniture, because V never referred to what was there before. This is the category to push everything into wherever possible. Declaring the destination value, rather than the operation that reaches it, lets data inherit the same path-independence that structure already enjoys.

Idempotent, re-derivable rules

When the end value genuinely depends on existing content, for instance splitting a combined field into two columns, the specification is a rule rather than a constant. The rule is deterministic, so any road from a given starting point reaches the same result, but the result now depends on where one set out, because the source content was not knowable at authoring time. This remains safe provided the rule re-derives from a stable source rather than mutating in place: re-run, and it reproduces rather than accumulates.

Non-idempotent accumulators, forbidden

Anything of the form multiply by two, append a suffix, increment is non-idempotent. Applied twice it yields a different answer, and if the current state was reached by a road that already applied it, it over-applies. Here the route genuinely changes the data. These are the operations that put a system out of sync when a reorganisation or a patch runs twice or in the wrong order. The remedy is not to detect them more cleverly but to refuse to express migrations this way, forcing them into the re-derivable form above.

Change, delete-and-add, and merge

At the level of the resting value alone there is no difference between changing a cell to five and deleting a three then inserting a five: the cell holds five either way. They diverge the instant anything depends on identity or continuity. A change preserves the row's identity and everything hanging off it; a delete-and-add can orphan foreign keys, take a fresh surrogate key, fire delete-then-insert behaviour rather than an update, emit two events into any audit, change-data-capture or replication stream rather than one, and open a window in which the row is simply absent. The sharpest instance is a rename: rename A to B and drop A, add B reach an identical end structure, but the first preserves the column's data and the second destroys it.

This is the crux of the whole design. The end state under-determines the operation. A pure difference of two end states cannot recover whether a rename or a drop-and-add was intended, because both end states are the same picture. The path is not inferable, but it is entirely declarable. So the end state records where Rome is, and a separate channel of intent metadata records which properties of the journey are non-negotiable: identity preserved, data carried across, one audit event rather than two. Both are first-class. This is exactly why a pure difference engine loses information, and exactly what a superset earns its keep by recording rather than reconstructing.

Merge is a genuinely separate animal. Change, add and delete are deterministic once the source is known. Merge reconciles two already-populated states, and the moment both sides hold a value there is a conflict that no amount of staring at end states resolves. It requires a declared policy, last-writer-wins, source-of-truth precedence, field-level union, or refuse-and-flag, and that policy is a degree of freedom the other three do not carry.

04 Data governance

Four ownership policies and the three-way baseline

The data values that belong in the dictionary are default configuration values: the sensible starting values shipped with the system. The moment such a value is deliberately changed by the operator, that particular row passes out of the dictionary's governance while remaining, in every structural sense, a configuration row. Deciding correctly whether a given row is still governed is the single commonest place this class of system drifts, and it cannot be decided by comparing two values.

The naive test compares the current value against the dictionary's current default: equal means unchanged, different means the operator owns it. This is wrong in both directions. It reports a false change when the default itself moved between releases, so a row the operator never touched, still holding last release's shipped value, is wrongly judged owned and the new default fails to roll forward. And it reports a false match when the operator changed a value to something a later release then happens to ship as its new default, wrongly reclaiming a row the operator had taken. Both failures are silent.

The rule that prevents drift Retain, per instance, the value the dictionary last actually wrote into the row: an as-shipped baseline, stored or hashed alongside the data. Decide ownership by a three-way comparison. Current equals baseline means the operator has not touched it, so converge to the new value. Current differs from baseline means the operator owns it, so leave it and report it, whatever the new default says. The new value never enters the ownership decision; it enters only the convergence, and only after ownership is settled.

This is the mechanism that a well-designed package manager uses for its shipped configuration files, recording a checksum of what it shipped and comparing the current file to that record rather than to the new file, and that per-field ownership models reach from the other direction by having a defaulter relinquish a field the moment another actor writes it. That the same logic appears independently in both places is a good sign the ground is solid rather than invented.

Constraints and default metadata are not rivals

A column default and a dictionary seed row are not two homes for one fact. A column default governs an unbounded, unenumerable population: every future insert that omits the column. A dictionary seed row governs a finite, enumerated population: the specific rows shipped. For the omitted-insert population the engine-enforced constraint should be primary, because it is applied at write time, is universal, and cannot lag a reconcile run. The dictionary's role there is not to duplicate the value but to own the constraint's definition as a structural object, so the constraint is itself governed and diffable across releases. The constraint therefore sits inside the dictionary as structure, while the seed rows sit inside it as data.

Four policies, not a binary

Governance is not simply in-dictionary or out. Every managed attribute carries an ownership policy, of which there are about four. Fully enforced, where the dictionary always wins and drift is corrected, which is where nearly all structure lives. Managed-until-overridden, the configuration defaults, reconciled while untouched and relinquished on local change, which is the category needing the three-way baseline. Set-once, seeded at creation and never touched again, such as an initial credential or a created-on stamp. And unmanaged, purely operational or transactional data the dictionary never asserts. The attribute that makes something managed-until-overridden is not its data type or its table but the willingness to relinquish it, and a wide set of attributes beyond configuration values share those exact semantics and can ride the same machinery: feature flags shipped on or off, default access grants and role seeds, customisable menu items, report and form definitions, default thresholds, translatable label strings, and default scheduled-job definitions. All break in the same way if ownership is decided by a two-way comparison.

05 Versioning

The dictionary as a composed, content-addressed lineage

The dictionary should not live as an opaque flat file. It should be text held in a version control repository, from which the flat file is compiled as a build artefact at convergence time rather than being the source of truth. Once the desired state is text under version control, history, branching, difference, blame and merge come for free, and the addressed-version graph becomes ordinary commits.

The dictionary itself should be composed from ordered layers rather than authored as one blob. The base install is a layer, each patch set is an immutable layer, local customisation is a layer, and the effective target is a deterministic fold over that stack. Giving each resulting dictionary version a content address, a hash of its inputs, makes identical states share identical identifiers, so history becomes a directed graph of versions rather than a list. Rolling a patch set forward is pushing a layer; rolling one back is popping it and re-composing. The engine converges toward any addressed version, forward or back, without caring which direction time runs.

Reporting over time then falls out for free by separating plan from apply. The plan is a reviewable, storable artefact and is itself the changelog. Stored with who ran it and when, it is an audit record; and any two dictionary versions can be differenced directly to answer what changed between one release and another, independently of what was actually applied anywhere.

06 Two parties

Vendor and customer changes as a three-way merge

The hardest real problem in this class of system is that two parties change the same governed metadata. The company changes shipped defaults through patches and releases; the customer changes those same values through configuration, tuning and customisation. Both are legitimate, both edit the same objects, and on the next release the two must be combined without the vendor overwriting the customer or the customer's edits blocking the vendor's structural changes.

This is a three-way merge, and it is the per-instance baseline expressed as branches. The vendor's shipped dictionary is one branch. The customer's live configuration is another, forked from a specific vendor release. The common ancestor is the exact vendor baseline the customer started from. With all three points, every value classifies the way a line-merge classifies every line. Vendor changed it and customer did not: take the vendor's, the new default rolling forward correctly. Customer changed it and vendor did not: keep the customer's, the override surviving. Neither changed it: no action. Both changed it: a genuine conflict, and the only case needing a human or a declared policy. The ancestor is what separates nobody touched this from both touched this, which is precisely why the baseline must be retained per customer instance.

The discipline that keeps this from rotting is to hold the two parties' changes in physically separate layers, never interleaved in one file. Vendor content is one set of files the customer never edits; customer overrides are a separate set; the effective dictionary is composed by overlaying the second on the first. A vendor patch is then a clean update into vendor-owned files that can never touch a customer file, the customer's overrides sit untouched through the upgrade, and reconciliation happens at compose time between two clean sources rather than as a struggle inside a shared document.

The conflict as a first-class object

A detected collision does not stop the world; it stops a component. When compose runs during the upgrade in the development environment, the both-changed cases are neither silently resolved nor allowed to halt the release. They are materialised as pending-conflict records: this value, on this row, vendor baseline was A, vendor now proposes B, customer currently holds C, status unresolved. That record is the unit of work. Everything without such a record is clean and flows straight through, so the upgrade half-applies by design, quarantining only the objects carrying an open conflict.

Resolution has exactly three outcomes, which closes the space. Take the customer's value, where the customer had deliberately tuned it and their intent wins. Take the vendor's value, where the local change was incidental or is now superseded. Or author a fresh value that reconciles both, the case where the vendor's change and the customer's change addressed different things that must now coexist, and the only case genuinely needing a human, because that reconciling value exists nowhere to be inferred. Each candidate is staged and tested in development against the impacted components, so the resolution is chosen on evidence rather than declared blind. The record then flips to resolved, carrying which candidate won and why, and the previously blocked components rejoin the testable set. Because that decision and its rationale live in the record, and the record lives in the repository, the system also captures for free the answer to why a given customer's value differs from the shipped default, the question that is otherwise impossible to reconstruct afterwards.

07 Dependencies

The impact graph: column-grained, provenance-marked, compiled not declared

Tying programmes, functions, screens and reports to the specific database objects they touch turns impact analysis into a query over a dependency graph. If a table changes, traversing every edge pointing at it yields the set of components that must be tested. This is the same graph used elsewhere in the design: during reconciliation it is walked to order operations, and for impact analysis it is walked to find blast radius. Same edges, a different question. A difference of database objects feeding an impact query is exactly what a documentation-and-cross-reference step does when it reports which business operations a schema change implicates.

Two refinements make the superset better than the cross-references it generalises. First, the edges should be column-grained and typed rather than table-grained. A table-level link answers only whether a component touches a table, which over-tests, because most changes are column-level and most components touch only some columns. Recording that a programme reads these columns and writes that one, that a report selects this column, that a screen binds that one, lets the impact query drop any component whose edges do not reference the changed columns, sharpening the test scope and shrinking both the blocked-by-conflict set and the retest set.

Second, the edges should be compiled, not declared. A cross-reference maintained by hand drifts the instant a component is edited and its declared dependency list is not, after which impact analysis quietly under-reports and an untested change ships. The accurate way to populate the graph is to derive the edges from source at build time, parsing what each component actually references, so the edges cannot fall out of step with the code they describe. Where the grammar of a language is fully controlled, this derivation is exact; where it is not, it is best-effort. The design therefore marks the provenance of every edge, engine-derived or declared-and-trusted, so a tester can be told whether an impact set is complete or is only as current as its hand-maintained associations. This is the property older cross-references did not carry, and it is what lets the system distinguish a load-bearing edge from a hint.

This also frames the honest choice between the two lineages the design generalises. One keeps dependency metadata beside heterogeneous code, which is language-agnostic but recovers the drift risk. The other expresses code, user interface and data reference in one ontology the engine reads directly, so the dependency graph is the source and there is no second artefact to drift, but at the cost of requiring that single language. The reconciliation is to layer them: keep the kernel and the graph language-agnostic, and supply a per-language provider that populates the edges from source with as much fidelity as that language allows, marking provenance throughout. The substrate is the first lineage; the derive-from-source discipline is the aspiration of the second, applied per provider and honestly labelled where it cannot be met.

08 Division of labour

Deterministic commands, artificial intelligence, and humans

A tempting shortcut is to abandon the metadata entirely: hand a model the before state and the after state, let it synthesise the transformation, and when it is wrong let the tests catch it and feed the failure back for a retry. For the structural, confluent part of the surface this would largely work, because any correct road to a structural assertion produces the identical result. But the design rests on the discovery that not all of it is confluent, and that is exactly where the model-only scheme fails in a way testing cannot rescue.

The end state under-determines the operation, so no model reasoning from two state descriptions can recover a rename from a drop-and-add: the distinguishing information is absent from its input, not merely hard to find. Path-dependent data means a model free to choose a different road on each retry can land on a different value each time, at odds with the reproducibility that is the whole selling point over the incumbent. And start over is not free once an operation has touched production data: structure can be re-derived, but a dropped column's data is gone. Worst of all, testing proves the presence of the paths tested and never the absence of the untested ones. A synthesised transformation can pass every written test and still corrupt the one customer whose data hits a case the tests did not cover, and with a black-box generator, tests passing is the only evidence there is. The failure is not a visible red at test time; it is a subtle wrong that shows green and surfaces at a customer site weeks after go-live, which is the very drift the superset exists to eliminate.

Where the intelligence belongs Point the model at drafting the deterministic migration artefact, which is then reviewed, version-controlled and applied by the ordinary reconciler; never make the black box itself the delivery mechanism. The model still needs the intent metadata for the cases the two states cannot express, because that fact is not in before-and-after and no amount of test-and-retry will conjure it. The metadata is not made redundant by the intelligence; it is the input that stops the intelligence guessing on the one class of operation where guessing loses data.

The mature division parcels the work by what each party does well. The deterministic commands own everything confluent and idempotent: the structural assertions, the identity-preserving operations, the re-derivable rules, because these produce the same Rome every time and can be run, re-run and rolled back mechanically. The intelligence owns the judgement-shaped work: drafting a migration from two states, proposing a resolution to a collision, suggesting the transform for a data-dependent rule, reading a test failure and proposing a fix, all places where the answer is not determined by the inputs. The human owns the intent neither can derive: that an operation is a rename, that the customer value wins here, the choice among candidate resolutions on test evidence. Three parties, each doing what only it does well, over one deterministic substrate that keeps the whole thing auditable regardless of which party proposed a given step. This is better than the incumbent, which had only the deterministic layer and paid for every judgement call in manual repair.

09 Recovery

Checkpointing along the dependency seams

Checkpointing makes the retry loop economical rather than brutal. Because the upgrade is already decomposed into discrete, individually testable operations over the dependency graph, the checkpoints are not arbitrary save-points but the natural seams of the work. Each operation, or each cluster that shares a fate, applies, is tested against its impacted components, and if green becomes a committed checkpoint. When something downstream fails, one rewinds to the last green checkpoint upstream of the failure and re-runs only from there rather than from bare metal. Each checkpoint is a content-addressed state, so rolling back is converging to an earlier address, and the addressing makes it certain which states remain valid and which are downstream of the failure and must be discarded. The dependency graph gives the blast radius, so independent branches keep their green checkpoints while only the failed subtree is lost.

The discipline that keeps rollback honest A checkpoint is a safe rollback target only if every operation between it and the failure is reversible or was snapshotted. A non-destructive, idempotent operation may checkpoint freely. A destructive one, dropping a column, deleting rows, may checkpoint only with a before-image captured into the checkpoint itself. Otherwise back up to the last green checkpoint is a lie, because the destroyed data does not return by re-running forward. Reversibility is decided per operation, and that decision is what tells the checkpoint machinery where it may promise a clean rollback and where it must carry a snapshot to keep the promise.

10 Orchestration

The campaign tracker and the derived go-live plan

Above the machine that performs the upgrade sits the orchestrator that runs the campaign: it holds a live model of where everything stands across update, upgrade, migrate and test, knows what is confirmed and what is outstanding, tracks what is next for the human and what must be captured and regressed, and emits the go-live plan as a derived artefact. This is the natural seat for the intelligence, because the job is inverted from migration synthesis. Here the model maintains a live picture that the humans and the deterministic commands are constantly checking against reality, so it cannot quietly corrupt anything; it can only get the bookkeeping wrong, and that shows up at once. The failure mode is benign where migration synthesis was catastrophic.

The load-bearing constraint The tracker is a projection of ground truth, never an authority over it. The substrate already knows which checkpoints are committed, which operations applied, which tests passed against which component versions, which conflict records are open. The tracker derives every status from that, and where a human action cannot be mechanically detected, the human's confirmation is itself recorded as a fact in the substrate, timestamped and attributed. A status board that can drift from the system it describes is worse than none, because people trust it.

The go-live plan then stops being a document someone writes and becomes a query result. The whole campaign is run once as a mock go-live in a staging environment, and every step, every operation, every test, every human confirmation, every resolution, is recorded as an event with its outcome, duration, dependencies and reversibility. The real plan is generated from that recorded run: the observed sequence, ordered by real dependencies, annotated with what was automated and what was manual, how long each phase took, where the rollback point sits at each stage, and where the go and no-go gates fall. The plan is not a forecast but a rehearsal transcript, which is what makes it trustworthy. The two failure modes of a hand-written runbook disappear: it cannot omit a step that actually has to happen, because every necessary step is in the recording, and it cannot include a stale one, because it is regenerated from the current run.

Across the lifecycle the tracker is one event log seen through a different lens per phase, and the phase gates are the structure. Inception and design produce the desired-state dictionary and the intent metadata, gated on a reviewed target. Build and unit test draft the operations and clear each against its own tests, gated on every operation individually green. System test runs the operations together in dependency order with impact-scoped tests, gated on an integrated run green with no open conflicts. User acceptance test exercises the customer-facing outcomes, with sign-off recorded as a fact rather than an email. The mock go-live produces the transcript. Go-live planning generates the plan from it. Go-live executes the plan against production with the checkpoints as the net. Post-go-live reconciles, verifying that actual matches intended, and folds the tests written along the way into the standing regression suite.

The one caveat to state plainly A mock certifies the sequence and the automation; it does not fully certify the data. It runs on staging data, and the recurring danger has been data-dependent transforms and data-triggered edge cases, so a rehearsal is only as predictive as its data is representative. The go-live plan should carry, per operation, what it assumed about the data and what it would do if that assumption is violated, and destructive operations must still capture their before-image even during the proven real run. Confidence in the data is bought by representative volume and shape in staging, ideally a dry run against a recent production clone rather than synthetic data.

11 Compounding

The regression flywheel

The tests that drive the loop are not throwaway. Every test written to validate an operation during an upgrade is, by construction, a regression test for that operation ever after, and the impacted-component test run to clear a checkpoint becomes the test that guards that component on the next upgrade. So the system does not merely get through this upgrade; it accretes a test suite as a side effect of doing upgrades, and each campaign starts with more coverage than the last. More of the loop can then run without waiting on a human, and proposed steps are validated faster and more completely each cycle. This is the payoff for insisting on a deterministic, testable substrate rather than a black box: only a substrate that produces discrete testable operations can produce reusable tests as exhaust.

12 Adoption

An elementary test bed before the ambition

The design does not have to arrive whole. The Solynth platform is small enough to serve as a live test bed for the ideas at an elementary level: a handful of tables, authentication, a knowledge repository with document names, a little authorisation logic, and small components linking out to external services such as Patreon, Spotify and Etsy. Each of these is a genuine instance of the pattern in miniature, and each can be used to refine the object model, the ownership policies, the dependency graph and the campaign tracker before any of it is asked to carry a large migration. Building the substrate against real but modest objects is how its abstractions are kept honest, and it means the first providers and the first conflict records exist against something one actually runs rather than against a specification.

13 Open decisions

What this strawman deliberately leaves unsettled

Several decisions are genuinely open and should be taken before this becomes a build specification. Terminology is provisional; the mapping below is a set of candidates chosen to stay distinct from the incumbent's vocabulary without inventing noise, and the working name for the system itself is a placeholder. Conflict-resolution cadence is undecided: whether the conflict set is surfaced as a single batch worked through before promotion, giving a clean gate, or resolved incrementally so that each closed conflict unblocks its own components and testing proceeds on the clean majority. The incremental model gets quality assurance moving sooner and matches the component-level quarantine, but the batch model is simpler to reason about at the promote step, and the right answer may differ by attribute class. Reversibility policy per operation type needs enumerating in full, since it drives both checkpointing and the before-image capture. And the merge-conflict default per attribute class, where the vendor and customer have changed the same value, needs settling: automatic policy for some classes, mandatory human decision for others.

Candidate terminology · provisional, for settling
Incumbent termIts roleCandidate
EnvironmentThe installed stack on a hostPlatform
Product lineVersioned unit of code and schemaCorpus / Assembly / Lineage
ApplicationA module within itApplication
Data areaAn instance sharing the code baseData area / Cell / Instance
DictionarySerialised desired stateManifest / Dictionary
Reorganise / upgradeThe reconcile stepConverge / Reconcile / Promote
VerifyAssert actual still matches expectedVerify / Assert
—Build the effective dictionary from layersCompose
—Produce the reviewable deltaPlan / Diff
—Converge toward an earlier addressed versionRevert

The command vocabulary deliberately leans on the plan-and-apply idiom and avoids naming a command after a category such as data-definition language, which names a kind of thing rather than an action.

Provenance and epistemic status

This note mixes three kinds of claim, and readers extending it should keep them apart. The architectural claims, confluence and idempotence as the safety properties, the object-and-provider kernel, the operation taxonomy, the three-way baseline, the column-grained impact graph, the checkpoint-reversibility rule, the tracker as a projection of ground truth, and the argument against a model-only migration scheme, are reasoned from first principles about the problem itself and do not depend on any particular product. They stand on that reasoning.

The descriptions of the incumbent systems, how the foundation and the later ontology-driven architecture tie programmes to tables, how their dictionaries are built from metadata, and how their configuration and audit facilities behave, rest on the author's direct professional experience of those systems over many years. They are reported here as that expert account and have not, in preparing this note, been re-verified against current vendor documentation; where an internal detail matters to a downstream decision it should be confirmed against the source.

The references to comparable external tooling, package-manager configuration handling, per-field ownership models, infrastructure and schema reconcilers of the state-based and migration-based kinds, are offered as prior art whose general shape is well established, but their specific current capabilities were not checked while writing and should be verified against each tool's own documentation before any is adopted as a starting point rather than built from scratch. Nothing in this note should be treated as a verified feature comparison.