Neo4j logoOutcomes

Four Things That Exist Afterwards

Adoption stories usually get told as a list of features. This one is easier to tell as an inventory: after a team wires CoreModels to their Neo4j instance, four artifacts exist that did not exist before, and almost everything that changes about the week is downstream of those four.

Four Things That Exist Afterwards

Adoption stories usually get told as a list of features. This one is easier to tell as an inventory: after a team wires CoreModels to their Neo4j instance, four artifacts exist that did not exist before, and almost everything that changes about the week is downstream of those four.

  1. A governed model of the graph — labels as Types, properties as Elements, outgoing typed relationships as references — that a person can open and read.
  2. An audit report that compares a fresh export of the graph against that model and returns counts, coded findings, and a markdown write-up.
  3. A status badge that renders the last recorded audit run as green, yellow, red, or gray.
  4. A Cypher constraint script, generated from the model, that makes the database enforce what the model says.

Here is what having them does to an ordinary week.

The import that starts it

One call, once: POST https://coremodels.example.com/graph/integrations/neo4j/import/{projectId} with Authorization: Bearer $TOKEN and the two artifacts you extracted — meta_schema from CALL apoc.meta.schema(), and optionally constraints from SHOW CONSTRAINTS. What comes back is a receipt rather than a shrug: datasetsAdded, datasetsSkippedExisting, fieldsAdded, nodesEnriched, snapshotStored, plus lossiness and errors arrays. A first import of a modest graph might report six datasets added, carrying thirty-nine fields between them — fieldsAdded itself reads zero on a first import, because it counts only fields added to already-governed labels on a re-import.

Behind those counts, uniqueness and existence facts land where a reviewer expects them: an existence flag becomes NotNull, a unique flag becomes Unique, and SHOW CONSTRAINTS rows refine both — a node-key constraint contributes uniqueness and existence to the property it covers. Node counts from the sampled schema ride along as metadata. Relationship-type entries in the APOC output are counted and skipped, because they duplicate what the node-side view already carries.

Tuesday, 09:40 — the pull request

A change to the ingestion job lands. CI extracts a fresh meta_schema.json against the staging instance and posts it to the machine-to-machine surface: POST https://coremodels.example.com/v1/{projectId}/integrations/neo4j/audit, authenticated with a user API key rather than a login token. The response is wrapped in the standard envelope, so the gate reads data.errorCount — greater than zero fails the build — and the job writes data.markdown into the step summary so the author sees the report without opening another tab.

This particular PR retyped a property. The audit reports it under Drift with the code field-type-drift, the subject names the exact field, and driftedObjects lists it for anything downstream that wants to react. Before, that change would have merged and surfaced weeks later as a comparison quietly returning fewer rows.

Tuesday, 11:15 — meaning moves, not the graph

A modeling review decides an identifier that has always been "usually unique" should be governed as unique. Someone makes that change in CoreModels — deliberately, by hand, because imports and audits never change meaning on their own.

Then the natural question: does the graph we already have still conform to the model we just tightened? That is one call with an empty {} body: POST https://coremodels.example.com/graph/integrations/neo4j/reaudit/{projectId}. It re-runs the same audit engine over the schema snapshot stored at import time, against the current governed model. No fresh export, no database access, nobody paged. The run always lands in the history, because a drift trail with gaps is not a trail.

Tuesday, 14:00 — someone asks the model instead of the graph

An engineer, mid-review, wants to know whether the OWNS relationship is governed to one target label or several. Rather than sampling nodes, they ask an assistant connected to https://coremodels.example.com/mcp over OAuth. get_vendor_integration_status with vendor: "neo4j" reports the last-import state; get_project_summary and search_nodes return the governed types and elements. The answer arrives with its caveat intact: the reference is governed to its first target, and the other labels are recorded.

Tuesday, 16:30 — the loop closes

The team wants Neo4j itself to enforce Tuesday's decision, so they call POST https://coremodels.example.com/graph/integrations/neo4j/generate/{projectId} with { "typeNames": [] } for everything eligible. Back comes one artifact, coremodels_constraints.cypher: CREATE CONSTRAINT ... IS UNIQUE for governed unique properties, CREATE CONSTRAINT ... IS NOT NULL for governed NotNull properties (with a header note that property-existence constraints require Enterprise), and CREATE INDEX for properties governed by a controlled vocabulary. Every statement is IF NOT EXISTS, so the script is safe to run twice. Reference elements are excluded by design — in Neo4j they are relationships, not properties.

The script goes through review like any other migration. Its header says, in the file itself, that meaning changes belong in CoreModels and the script should be regenerated rather than edited.

Friday — the badge

GET https://coremodels.example.com/v1/{projectId}/integrations/neo4j/badge returns image/svg+xml — the route is authenticated, so a pipeline job fetches it with an API key and publishes the file where the README can reference it. Green means the last recorded run was clean; yellow means warnings; red means errors; gray means nothing has been recorded yet. It is a small thing that ends a large category of conversation.

Before and after

BeforeAfter
Where the schema livesloaders, queries, memorya governed model with an owner
How drift is founda wrong query resulterrorCount on a pull request
Constraintswhatever someone rememberedgenerated from governed meaning, reviewed like code
Onboarding question"sample some nodes"open the model
Agent behaviorguesses structureconsults it over /mcp
Credentials we holdstill none

That last row is not a joke. There is no live Bolt or HTTP connection in this integration; the capability is declared and deliberately deferred. Everything above runs on two files you exported yourself.

What the after-state actually feels like

Boring, mostly. The questions that used to require an archaeology session — is this property required, is that key unique, which label does this relationship really point at, has anything changed since the last release — become lookups. The dramatic version of graph governance is an incident review. The undramatic version is a green badge, a clean audit on a Tuesday PR, and a constraint script that someone reviewed on Thursday afternoon.

Our Neo4j quickstart shows the same path — export, import, audit, re-audit, badge, generate — as concrete calls you can run today.