Commit 4db1bf1
feat(spec)!: retire the export-job API family, IExportService and ScheduleState (ADR-0049) (#20194)
Fixes #17158
Clause-②: no
Retires the export-job API contract family, the `IExportService`
contract (with `ScheduleExportInput`) and `automation/ScheduleState`
from `@objectstack/spec`: ADR-0049 enforce-or-remove, route 3 (whole-def
removal). Nothing ever served, bound or read any of them. The served
export door `GET /api/v1/data/:object/export` and the import-job family
in the same module are untouched.
## Rulings executed (quoted, not re-ruled)
- `5644350616`, decision batch #122 item 3, maintainer 「同意」: the family
in `api/export.zod.ts`, `IExportService` and `ScheduleExportInput` leave
the public surface through `RETIRED_DEFS_BY_MAJOR[18]` rows, one D3
semantic entry and refusal pins, with the `api-surface/` and
`json-schema.manifest/` ratchets moving and the reference pages
regenerated. `ScheduleState` goes too, "retired with the family unless a
live consumer is measured". **BREAKING** at `minor`, with the ADR-0087
disposition and `Clause-②: no`.
- `5815151991`, decision batch #221 item 2, letter A, 「同意」: objectui
retires its side first (objectui#10247), then this card retires the
whole family plus `ScheduleState` and carries the pin.
- `5825830323`, scope note, 「同意」: the export-job LIST pair
(`ListExportJobsRequestSchema` with `limit` default 20 / `cursor`, and
its response) is in. The import-job family (`ListImportJobs*`,
`ImportJob*`) is NOT, because it is served.
## Premise re-measured at this change's base (every zero beside a lit
control)
| reading | tree | family names (43) | control |
| --- | --- | --- | --- |
| objectstack, code outside `packages/spec` | base `49144fcc` | 0 code
files: only prose (2 unreleased changesets, generated reference pages,
`docs/qa` FOLLOW-UPS, 3 comment lines in the dogfood D7 ledger) |
`ImportJobProgress(Schema)`: 7 files |
| objectui at the pinned `.objectui-sha` `f8a9d0fb0596` | pin | 0
non-markdown files; the only hits are CHANGELOG prose recording
objectui#10247 | `ImportJobProgress` 7,
`GetMetaItemLayeredResponseSchema` 9, `@objectstack/spec/api` 34 |
| cloud `main` | `48d70663` | 0 files (`git grep` exit 1) |
`@objectstack/spec`: 537 files |
| served routes | base | `@objectstack/rest` mounts no
`/api/v1/data/export` route and no `POST` on
`/api/v1/data/:object/export`; the route ledger lists only `GET
/api/v1/data/:object/export` | the `import/jobs` routes are served and
ledgered |
| ADRs naming the family | base | 0 (`git grep` exit 1) |
"enforce-or-remove": 43 ADRs |
**Pin: not moved.** objectui#10247 landed as objectui PR #10264, merge
`8b1f066192a4`. `git merge-base --is-ancestor 8b1f066192a4 f8a9d0fb0596`
exits **0**, which is self-proving on any checkout, and the pin is 58
commits ahead of it and 0 behind. The ruling's pin condition is already
met, so `.objectui-sha` is untouched.
**`ScheduleState`: no live consumer** in any of the three repos (the
rows above include its three names), so it retires per ruling item 2.
## What leaves the surface
- `@objectstack/spec/api`: `ExportJobStatus`; `CreateExportJobRequest*`
/ `CreateExportJobResponse*`, `ExportJobProgress*`, `ScheduledExport*`,
`GetExportJobDownloadRequest*` / `GetExportJobDownloadResponse*`,
`ListExportJobsRequest*` / `ExportJobSummary*` /
`ListExportJobsResponse*`, `ScheduleExportRequest*` /
`ScheduleExportResponse*` (Schema consts, input aliases, Parsed
aliases); and `ExportApiContracts`.
- `@objectstack/spec/contracts`: `IExportService`,
`CreateExportJobInput`, `CreateExportJobResult`, `ExportJobDownload`,
`ListExportJobsOptions`, `ExportJobListResult`, `ScheduleExportInput`.
The module `contracts/export-service.ts` and its test are deleted, and
the barrel line is replaced by a note.
- `@objectstack/spec/automation`: `ScheduleStateSchema`,
`ScheduleState`, `ScheduleStateParsed`.
- Stays: `ExportFormat`, `ExportImportTemplateSchema`, the import
validation shapes, the whole import-job family including
`ImportJobApiContracts`, and `GET /api/v1/data/:object/export`.
## Route and registration (ADR-0087)
Route 3: none of these shapes is a stack collection or a metadata type,
so there is no carrier key for a `retiredKey()` tombstone and no
authored document for a D2 conversion. The declaration is:
- 13 `RETIRED_DEFS_BY_MAJOR[18]` entry files under
`migrations/entries/retired-defs/`: 12 `api/…` plus
`automation/ScheduleState`.
- The D3 semantic entry `export-job-family-retired`, whose `reason`
states why it is not a D2 conversion.
- `registry.ts` regenerated by `gen:migration-registry`. The step-18
`rationale` is not touched.
- The route's own evidence, kept as proof. The first `gen:schema`
refused with `❌ 13 previously published schema(s) disappeared from this
build`, naming exactly the 13 defs. After the deliberate manifest
deletion, the build reads each one as `json-schema/api/….json —
RETIRED_DEFS_BY_MAJOR, major 18.`, and the authorable-surface gate
records `12 baseline deletion(s) … carry their own proof (#4650)`, each
`def no longer emitted by this build`. `ExportJobStatus` is an enum with
no key rows.
Ratchet movement is all removals, as a whole-def removal must show (an
enum-value narrowing would show none):
| artifact | lines |
| --- | --- |
| `json-schema.manifest/{api,automation}` | −12 / −1 |
| `authorable-surface/{api,automation}` | −67 / −16 |
| `authorable-defaults/{api,automation}` | −7 / −4 |
| `api-surface/{api,automation,contracts}` | −34 / −3 / −7 |
| `export-origins/{api,automation,contracts}` | −33 / −3 / −7 |
| `declaration-map/{api,automation}` | −23 / −2 |
`authorable-surface.base.json` is untouched (written only by
`gen:authorable-surface-base`).
## Changed prose, quoted for the contract review
No `.describe()` or refusal text changed; the removed schemas' describe
strings left with them. Four docblocks changed:
- `api/export.zod.ts` module docblock, which renders into
`content/docs/references/api/export.mdx`: "The export the platform
serves is the synchronous streaming door `GET
/api/v1/data/:object/export`, which answers the file itself as CSV, JSON
or XLSX. The asynchronous export-job API that used to be declared here
(export jobs, their progress / download / list shapes, scheduled exports
and `ExportApiContracts`) was never served by any route and was removed
in @objectstack/spec 17 (ADR-0049 enforce-or-remove); a recurring export
is a `Job` whose handler you write."
- `ImportJobStatus` docblock, which used to link the retired enum:
"Import Job Status — the states the import worker actually moves a job
through (`succeeded`, not `completed`, is the success terminal)."
- `RunListResult` docblock (`contracts/automation-service.ts`), which
cited `ExportJobListResult`: "Unlike a cursor-paged list shape, and
deliberately: there is ⛔ NO `nextCursor` here."
- The retirement notes at the old section 2 of `api/export.zod.ts` and
section 6 of `automation/execution.zod.ts`, plus the
`contracts/index.ts` barrel note (code comments, not rendered).
The prose says "@objectstack/spec 17" and not 18, because
`check:future-spec-major` requires naming the release line (ADR-0087
amended): a pre-GA retirement ships as a `minor` of 17. The registry
rows stay under major 18.
## Pins (new and flipped)
- **New** `packages/spec/src/api/export-job-family-retirement.test.ts`
(7 tests; added to `vitest.repo-tests.json`, `repo` project). It follows
the `system/compliance-families-retirement.test.ts` form:
- zero holders on every public entry for all 43 names via
`export-origins/`, with survivors on `./api`, `./automation` and
`./contracts`;
- the runtime namespaces agree;
- `contracts/export-service.ts` is gone, with no in-package importer;
- the 13 defs are absent from `json-schema.manifest/`, and the 43 names
from the `api-surface/`, `declaration-map/` and `export-origins/`
shards, each with a lit control;
- no authorable rows remain under the defs;
- registration: all 13 defs in `RETIRED_DEFS_BY_MAJOR[18]`, the D3 entry
wired with its "not a D2 conversion" reason, a backtick-free `surface`,
a `replacement` naming the import-job family as NOT retired, and no
conversion id for the family;
- a **tree-scoped absence** leg over `packages` / `examples` / `skills`
/ `content` / `scripts`. That radius is already declared for
`@objectstack/spec` in `scripts/cross-package-test-inputs.mjs` and
`turbo.json`, and `check:cross-package-test-inputs` is green.
- **Flipped** `cron-typed-positions-retirement.test.ts`: the three sites
whose defs retire whole (`ScheduledExport` / `ScheduleExportRequest`
`schedule.cronExpression`, `ScheduleState.cronExpression`) move to
`LEFT_WITH_THEIR_DEFS`. Two facts stay asserted: no key-level
registration ever, and each enclosing def is now a
`RETIRED_DEFS_BY_MAJOR[18]` entry (dark control
`integration/DataSyncConfig`). The four live positions are pinned
unchanged, and the envelope case now uses `CacheWarmup.schedule`.
- **Flipped** `type-alias-convention.pin.test.ts`: the three isomorphic
pins leave with their schemas, 790 → 787, receipt added.
- **Removed with their subjects**: the family's blocks in
`api/export.test.ts`, the `ScheduleStateSchema` block in
`automation/execution.test.ts`, and `contracts/export-service.test.ts`.
## Ablations (one-shot; the fix was committed first;
`scripts/ablation-replace.mjs` wrap mode under `trap … EXIT INT TERM`
with absolute paths)
The subject resolves from `src/` and committed JSON (no package
specifier, no `dist/`), so no rebuild is needed per leg. These ran at
`6c35939e`.
| leg | mutation (on disk: anchor count → 0, blob moved) | result |
| --- | --- | --- |
| A1b | re-plant `ExportJobStatus` const + type in `api/export.zod.ts`
(blob `501ee4a5` → `2d84be39`) | RED 2: "runtime namespaces agree…"
(`api must not export ExportJobStatus`) and the tree-scoped leg
(`packages/spec/src/api/export.zod.ts references typeof
ExportJobStatus`) |
| A2 | delete `'automation/ScheduleState',` from the generated
`RETIRED_DEFS_BY_MAJOR[18]` region (blob `6a3b0b58` → `58ab1619`) | RED
2: "declares all thirteen defs…" and the cron file's "[#17158] … covered
at DEF grain" |
| A3b | re-add `"api/ExportJobStatus"` to
`json-schema.manifest/api.json` (blob `8c11f3d0` → `5ea54e58`) | RED 2:
"the generated shards…" (`must have left json-schema.manifest/`) and the
tree-scoped leg |
- Every restore was proven: blob equals HEAD, and `git diff HEAD` is
empty.
- 1 parent 560b724 commit 4db1bf1
46 files changed
Lines changed: 970 additions & 2074 deletions
File tree
- .changeset
- content/docs/references
- api
- automation
- docs/audits
- packages/spec
- api-surface
- authorable-defaults
- authorable-surface
- declaration-map
- export-origins
- json-schema.manifest
- src
- api
- automation
- contracts
- migrations
- entries
- retired-defs
- semantic
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
0 commit comments