Mirrored from
upstream-contract/README.mdat commitf31ec6a. Edit the file in the repository: this page is regenerated from it, and edits made here are overwritten.
Upstream contract tests
Unit tests that fail when upstream moves something this bundle depends on.
Normally you do not run these directly — scripts/check-upstream.sh runs them
along with the pin invariant and the patch/typecheck pass, and CI
(.github/workflows/test.yml) runs that on main, testing and every PR. To
run just this suite:
pnpm --filter server exec jest --testPathPatterns upstream-contract
No database, no container, no Nest boot — they read source files off disk and finish in seconds, so they can run on every commit.
The problem they solve
This fork depends on core in three ways, and only one of them is type-checked:
| seam | breaks how | caught by |
|---|---|---|
| static imports of core services | build error | tsc |
| files our patches edit | patch fails to apply | scripts/verify-patches.sh |
require() hooks and raw SQL |
silently, at runtime | these tests |
The third row is the dangerous one. Core loads every EE feature with a bare
require(<string>) wrapped in try/catch, so a path that no longer matches is
not an error — it means "not bundled", and the feature simply disappears.
Postgres functions named inside a sql template are resolved at execution
time, so a dropped one is a 500 on one endpoint and nothing anywhere else.
What each file checks
hook-inventory.ts — every core→EE hook as data: path, export, call sites,
who owns the call site, whether we implement it, and for unimplemented ones a
note on what the user loses. This is the list di-check.ts keeps informally;
here it is machine-readable so both halves can be checked against it.
core-ee-hooks.spec.ts — both directions:
- their side — every call site recorded in the inventory still exists in core and still reads the same exported name;
- their side, completeness — scans all of core for
require('…ee/…')and fails on anything the inventory does not list. This is the new-feature detector: upstream adding a hook is otherwise invisible; - our side — implemented hooks export the symbol core reads; unimplemented ones have no file at all, because a stub makes core take the "bundled" branch and then fail per request.
core-sql-objects.spec.ts — the Postgres functions and extensions our raw
SQL calls (base_cell_*, jsonb_set_many, f_unaccent, unaccent,
pg_trgm) are still created by a migration, with the arity we call them with.
Relationship to di-check.ts
They are complements, not duplicates.
di-check.ts boots a real app in the container and asks whether our exports
resolve through the DI container — the only way to catch a class that is
exported but not registered as a provider, which is how the api-key hook once
broke. It cannot run in CI per commit, and it treats core's half of each
contract as a comment.
These specs check the half di-check assumes, and cost seconds instead of a container. Neither replaces the other:
| di-check.ts | these specs | |
|---|---|---|
| core still calls the hook | no | yes |
| upstream added a hook | no | yes |
| our export exists | yes | yes |
| our export resolves in DI | yes | no |
| needs a running instance | yes | no |
When one fails
A hook vanished or moved — upstream dropped or renamed it. Find the new call site, update the inventory, and check whether the feature still works.
An unknown hook appeared — upstream shipped an EE feature we do not have.
Either implement it, or add it to the inventory with implemented: false and
an unimplementedNote recording what users lose. Both are fine; leaving it
undecided is not, because the failure mode is a feature that is quietly missing.
A SQL function changed — do not just update the expected arity. Our callers
pass a fixed argument list; find them via the usedBy field and fix those too.
Worked example: what this caught
Moving the pin from 7439da2f to 5b854645 added exactly one hook,
oauth/services/oauth-strategy.service, from upstream's MCP OAuth work
(e56de8eb). Nothing else would have reported it — it type-checks, no patch
touches it, and core's try/catch turns the miss into silence. It is recorded in
the inventory as unimplemented: MCP clients cannot authenticate against this
build, and nothing else regresses.