Roadmap
Phase 1 — MVP (Foundations) ✓
- SemblanceAPI core
- GET endpoints
- Query parameter inputs
- Single & list outputs
- FromInput binding
- DateRangeFrom constraint
- Polyfactory integration
- FastAPI app export
- Basic pytest client
Phase 2 — Practical Expansion ✓
- POST endpoints with body models
- Path parameter support (GET and POST)
- Pagination helpers (PageParams, PaginatedResponse)
- Deterministic seeding (SemblanceAPI(seed=), seed_from=)
- Error response simulation (error_rate, error_codes)
- Response count / limit constraints (list_count=, list_count="field")
Phase 3 — Advanced Simulation ✓
- Conditional dependencies (WhenInput)
- Cross-field constraints (ComputedFrom)
- Collection filtering constraints (filter_by=)
- Nested model linking
- Optional stateful mode (SemblanceAPI(stateful=True))
- Latency & jitter simulation (latency_ms=, jitter_ms=)
Phase 4 — Ecosystem & Polish ✓
- Plugin system for custom links
- OpenAPI schema annotations (summary, description, tags)
- CLI runner (
semblance run,semblance export) - Frontend mock export (OpenAPI + fixtures)
- Documentation site (MkDocs)
- Example galleries
Phase 5 — Testing & Validation ✓
- Property-based testing — Hypothesis integration:
strategy_for_input_model(),test_endpoint()insemblance.property_testing; generate inputs from input models, validate responses match output schema and optional invariants - PUT, PATCH, DELETE endpoint support
- Optional response schema validation —
SemblanceAPI(validate_responses=True)verifies generated responses conform to output model - Rate limiting simulation —
rate_limit=Nrequests per second per endpoint (sliding window, 429 when exceeded)
Phase 6 — Stateful CRUD & Export ✓
- Stateful PUT/PATCH/DELETE ✓ — When
stateful=True, PUT upsert by path + id, PATCH update by id, DELETE remove by id; extendStatefulStorewith get-by-id, update, remove so list GET and single-item GET/PUT/PATCH/DELETE use stored data - Export and CLI ✓ — Include PUT, PATCH, DELETE in
export fixturesand OpenAPI example generation (minimal body/path params);_sample_requestand schema iteration extended for put/patch/delete - OpenAPI polish ✓ — Document 429 response when
rate_limitis set; optional response descriptions for simulated error codes (4xx/5xx)
Phase 7 — Developer Experience & Extensibility ✓
- Built-in request links ✓ —
FromHeader(name),FromCookie(name)for binding output fields to request headers/cookies (withregister_link-style resolution) - Config file ✓ — Optional defaults from
[tool.semblance]in pyproject.toml orsemblance.yaml(e.g. seed, validate_responses, stateful) viaSemblanceAPI(config_path=...)orSemblanceAPI.from_config() - Pytest plugin ✓ — Markers
@pytest.mark.semblance(app="module:attr")and@pytest.mark.semblance_property_tests(app="..."); fixturessemblance_api,semblance_client; parametrized property tests per endpoint - Reproducible failures ✓ — On Hypothesis failure in
test_endpoint, error message includes "Reproduce with curl:" and "Or Python:" snippets - Mount and middleware ✓ —
api.mount_into(parent_app, path_prefix);api.add_middleware(MiddlewareClass, **kwargs)applied inas_fastapi()
Phase 8 — UX & Ergonomics ✓
- CLI onboarding
semblance init— scaffold a minimal runnable app (+ optionalsemblance.yaml)semblance validate module:attr— validate routes/links/config without starting a server (CI/pre-commit friendly)semblance run module— infer:api/:appwhen unambiguous; improve--helpwith copy/paste examples- Faster-to-fix errors
- Validate link bindings at
as_fastapi()(e.g.FromInput("typo")) with route/model/field in the error - Improve duplicate endpoint errors (include HTTP method + path + where possible)
- Enrich stateful by-id errors (404 includes collection + id field/value, optionally behind a flag)
- Docs that answer “why did this happen?”
- Troubleshooting / FAQ page (common 404/422/429/stateful/link issues)
- Short “Concepts” overview (input/output models, links, seeding, stateful store, simulation options)
- Cookbook/recipes page (pagination, stateful CRUD, request links, rate limiting, property tests)
Phase 9 — External API Mock Packages: Foundry ✓
Ontology-read MVP for an unofficial semblance-foundry adapter. Detailed spec: Semblance Foundry Package Plan. Workspace pythonpath / ruff / mypy plumbing lives in Phase 11; Foundry tests plug into those paths rather than duplicating CI matrix work here.
- Package bootstrap ✓ —
packages/semblance-foundry/withpyproject.toml,semblance_foundryimport,FoundryMock/FoundryMockConfig, CLI (serve,validate,fixture init,operations), tests layout, unofficial/non-affiliation notice. Independently versioned; depends onsemblancevia a normal version range. - Compatibility model ✓ — per-operation
compatibility.yamlwith support levelsexact|representative|stub|unsupported, docs URL + verification date (public API v2, dated 2026-08-18 unless a newer pass is recorded), and tests that prove the level; expose/.well-known/foundry-mock-compatibility.json. Unknown paths return 404; known-but-unimplemented operations may return 501 only instrictmode. - Fixture-backed ontology graph ✓ — YAML/JSON fixture v1: one ontology, two object types, links, one action type (metadata only), one query type; deterministic RIDs; load-time validation (duplicate API names / primary keys). Process-local state only; no restart durability.
- Ontology read operations (MVP) ✓ — public API v2:
GET /api/v2/ontologiesGET /api/v2/ontologies/{ontology}GET /api/v2/ontologies/{ontology}/objectTypesGET /api/v2/ontologies/{ontology}/objectTypes/{objectType}GET /api/v2/ontologies/{ontology}/objects/{objectType}GET /api/v2/ontologies/{ontology}/objects/{objectType}/{primaryKey}POST /api/v2/ontologies/{ontology}/objects/{objectType}/search(representative: eq/and filters only)GET /api/v2/ontologies/{ontology}/objects/{objectType}/{primaryKey}/links/{linkType}GET /api/v2/ontologies/{ontology}/actionTypesand get-by-name (metadata; no apply)GET /api/v2/ontologies/{ontology}/queryTypesand get-by-namePOST /api/v2/ontologies/{ontology}/queries/{queryApiName}/execute(static fixture or allow-listed Python callback; never eval fixture expressions)- Auth, errors, pagination ✓ — auth modes
disabled,optional(default), andstrict; Foundry-style error envelope; opaque checksummed page tokens owned by the adapter (PageTokenCodec); request-id header. Do not add Foundry-shaped helpers to core unless a second adapter immediately needs the same primitive. - Testing surface ✓ —
FoundryMock.as_fastapi(), pytest context/fixtures, golden HTTP contracts. HTTP contract tests are required; one pinnedfoundry-platform-sdkversion is the compatibility acceptance test (optional/non-blocking if the SDK cannot target localhost in CI). No live Foundry; no network in unit/contract tests. - Exit criterion ✓ — HTTP client (and SDK if CI-feasible) lists fixture objects across two pages, gets by primary key, follows one link, and executes one configured query — all locally.
Later (see Foundry plan)
Not Phase 9: apply/applyBatch actions, aggregates, object sets, datasets/transactions, orchestration/streams, Foundry 1.0. Those are post–Phase 9 milestones in the Foundry plan.
Phase 10 — External API Mock Packages: Databricks ✓
Unofficial semblance-databricks adapter covering workspace compute, jobs, artifacts, permissions, and SQL statements (phases A–D). Detailed spec: Semblance Databricks Package Plan. Workspace pythonpath / ruff / mypy plumbing lives in Phase 11; Databricks tests plug into those paths rather than duplicating CI matrix work here. DatabricksMock is a custom FastAPI factory (same reason as Foundry: core ignores handler bodies). Independently versioned; depends on semblance>=0.7.0,<0.9. Public REST pinned 2026-08-19 (Jobs 2.2, Clusters 2.1, SQL/DBFS/secrets/permissions 2.0).
- Package bootstrap ✓ —
packages/semblance-databricks/withpyproject.toml,semblance_databricksimport,DatabricksMock/DatabricksMockConfig, CLI (servedefault port 8766,validate,fixture init,operations), tests layout, unofficial/non-affiliation notice. - Compatibility model ✓ — per-operation
compatibility.yamlwith support levelsexact|representative|stub|unsupported, docs URL + verification date, and tests that prove the level; expose/.well-known/semblance-databricks-compat.json. Unknown paths return 404; known-but-unimplemented operations may return 501 only instrictmode. Optional Jobs 2.1 aliases arerepresentative, not primary. - Fixture-backed workspace ✓ — YAML/JSON fixture v1: bundled
acmewith clusters spanning two list pages, ≥2 jobs, ≥1 run, warehouse, secret-scope metadata (no secret values on REST), DBFS stubs, one workspace path. Deterministic IDs; load-time validation. Process-local state; capped temp-dir opt-in for DBFS only. - Phase A — reads ✓ — public REST:
GET /api/2.1/clusters/listandGET /api/2.1/clusters/getGET /api/2.2/jobs/list,GET /api/2.2/jobs/get,GET /api/2.2/jobs/runs/getGET /api/2.0/workspace/get-status(object path, not workspace health)GET /api/2.0/preview/scim/v2/Meif the pinned SDK requires current user- Phase B — writes and lifecycle ✓ — cluster create/edit/delete/restart; jobs create/reset/delete; runs submit/cancel; SQL warehouses
/api/2.0/sql/warehouses; workspace secretsGET/POST /api/2.0/secrets/...(keys only). Virtual-clock cluster/run states (PENDING→RUNNING/ERROR, cancel →TERMINATED). - Phase C — artifacts ✓ — libraries install/uninstall,
GET /api/2.2/jobs/runs/get-output, cluster events, DBFSlist/readandPOST /api/2.0/dbfs/add-blockstub. No invented audit-log URLs. - Phase D — permissions and SQL ✓ —
GET/PATCH /api/2.0/permissions/{object_type}/{object_id};POST/GET /api/2.0/sql/statements(fixture or allow-listed callback chunks; no Spark SQL). - Auth, errors, pagination ✓ — auth modes
disabled,optional(default), andstrict; Databricks{error_code, message}(not Foundry envelopes); opaque checksummed page tokens owned by the adapter (PageTokenCodeccopy); request-id header. Do not add Databricks-shaped helpers to core in Phase 10. - Testing surface ✓ —
DatabricksMock.as_fastapi(), pytest context/fixtures, golden HTTP contracts. HTTP contract tests are required; one pinneddatabricks-sdkversion is the compatibility acceptance test (optional/non-blocking if the SDK cannot target localhost in CI). No live Databricks; no network in unit/contract tests. - Exit criterion ✓ — HTTP client (and SDK if CI-feasible) lists fixture clusters across two pages, gets a cluster and job, gets a run, drives one virtual-clock write (create/restart cluster or submit/cancel run), lists secret keys without values, and hits get-status plus one SQL statement or permissions get — all locally.
Later (see Databricks plan)
Not Phase 10: Unity Catalog (including UC secrets), Model Serving, Spark Declarative Pipelines / DLT, Jobs 2.0 as primary, OAuth, Databricks adapter 1.0. Those are post–Phase 10 in the Databricks plan.
Phase 11 — Core Infrastructure for Multi-Package Development ✓
Workspace plumbing so core + both adapters develop from one environment without path hacks. Do not extract PageTokenCodec (or other vendor-shaped helpers) into core in this phase; Foundry and Databricks copies wrap different error types. Leave extraction for a later phase if the codecs stay identical.
Already in tree
- Root
pyproject.tomlpytestpythonpath, ruffsrc, and mypymypy_pathincludesrc/,packages/semblance-foundry/src, andpackages/semblance-databricks/src. - CONTRIBUTING and README document editable installs for core + both adapters.
- Workspace lint, mypy, and security jobs cover all three packages.
Remaining work (done)
- CI slices ✓ — Pytest matrix
package: [core, foundry, databricks]on the same OS/Python matrix,-m "not sdk". Lint/mypy/security stay workspace-wide. Each slice reports coverage for that tree. - Install/cache hygiene ✓ — Pip cache keys hash all three
pyproject.tomlfiles. README Development and CONTRIBUTING use the three pytest slices. - Dependency boundaries ✓ —
tests/test_package_boundaries.py: adapters do not import each other orsemblance._*. Rootdevextra pinsruff==0.16.3; adapter[dev]extras remain for package-only installs. - Tree hygiene ✓ — Unpack glob ignored; ruff excludes
semblance_*-*leftover sdist dirs. - Docs ✓ — CONTRIBUTING clean-clone block; publishing example tags
v0.8.0/foundry-v0.1.2/databricks-v0.1.1.
Release versions
| Package | From | To | Tag |
|---|---|---|---|
semblance |
0.7.0 | 0.8.0 | v0.8.0 |
semblance-foundry |
0.1.1 | 0.1.2 | foundry-v0.1.2 |
semblance-databricks |
0.1.0 | 0.1.1 | databricks-v0.1.1 |
Adapters depend on semblance>=0.7.0,<0.9. Publish order: core v0.8.0 first, then adapter tags (tagging is a separate step; see publishing).
Acceptance
- From one venv: editable installs of all three packages; both adapters build and test without path hacks.
- CI uses independent test slices.
- Versions and changelogs dated for 0.8.0 / 0.1.2 / 0.1.1.
Phase 12 — Declarative Simulation APIs ✓
Core APIs so downstream simulators stop dropping to Starlette middleware and one-off handlers. GitHub issues #1 and #3–#10 are the Phase 12 backlog; this phase ships the core-library slice plus adapter dependency-range bumps. Issues were written against consumer simulators (tests/simulators/…) that are not in this repo — implement against SemblanceAPI / link plugins, do not import those files.
Do not extract PageTokenCodec (or other vendor-shaped helpers) into core. Do not replace Foundry/Databricks auth modes or error envelopes. Adapters keep custom FastAPI factories (handlers are still ignored by core). Native bytes/streaming (#2) waits until an in-tree adapter needs /content or /upload.
Prefer backward-compatible defaults; new strictness is opt-in.
Already in tree
- Pydantic input models already validate query, path, and body (#6 is mostly this).
WhenInputfor conditional field links;FromHeader/FromCookiefor request binding.PageParams/PaginatedResponsefor offset/limit lists; adapters own opaque page tokens.- Route
error_rate/error_codes;stateful=True+StatefulStorefor CRUD-shaped mutation. - Adapter Bearer (
disabled/optional/strict) and vendor error JSON — not core route auth.
FromJsonFixture / FromNestedFixture are built-in links (they did not exist before this phase).
Remaining work (done)
- Route Bearer (#1) ✓ —
bearer_tokens=on the route; 401 without echoing tokens. Adapters unchanged. - Error maps (#7, #8) ✓ —
ErrorCasepredicates; complementserror_rate. - Fixture links (#3, #4, #5) ✓ —
FromJsonFixture/FromNestedFixture; default miss non-strict. - Pagination fixtures (#9) ✓ —
PageTable/PageSlice; noPageTokenCodecin core. - Scenario steps (#10) ✓ —
ScenarioStepsequence; holds last.StatefulStoreremains CRUD. - Validation docs (#6) ✓ — Cookbook for Pydantic
Field/Literal; no parallel validator. - Adapter ranges ✓ —
semblance>=0.8.0,<1.0; no new Foundry/Databricks operations.
Not this phase
- #2 binary/streaming bodies and content-type overrides.
- Foundry apply/datasets/content, Databricks Unity Catalog / serving (still post–Phase 9 / 10).
- Migrating adapter routers onto core Bearer, error maps, or fixture links.
- Extracting
PageTokenCodecinto core.
Issue routing
| Issue | Owner | Phase 12 |
|---|---|---|
| #1 Bearer routes | core | done |
| #2 binary bodies | core | later |
| #3 conditional fixtures | core | done |
| #4 fixture-miss strict | core | done |
| #5 collection selectors | core | done |
| #6 param validation | core | done (docs) |
| #7 status/body errors | core | done |
| #8 invalid-input errors | core | done |
| #9 pagination fixtures | core | done |
| #10 scenario steps | core | done |
Mark a row done only when code, tests, and user-facing docs for that issue are in tree. Close the GitHub issue in the same change.
Release versions
| Package | From | To | Tag |
|---|---|---|---|
semblance |
0.8.0 | 0.9.0 | v0.9.0 |
semblance-foundry |
0.1.2 | 0.1.3 | foundry-v0.1.3 |
semblance-databricks |
0.1.1 | 0.1.2 | databricks-v0.1.2 |
Adapters depend on semblance>=0.8.0,<1.0 so 0.9.x installs (today’s <0.9 would block it). Publish order: core v0.9.0 first, then adapter tags (publishing).
Acceptance
- In-scope issues (#1, #3–#10) implemented or documented as specified; #2 still open and pointed at a later phase.
- Defaults unchanged for existing apps; strict fixture-miss and Bearer are opt-in.
- Adapters still build against core without using the new helpers internally.
- CI slices stay green; changelogs dated for 0.9.0 / 0.1.3 / 0.1.2.