Feature design: Self-service capability discovery and Studio v1¶
- Status: IMPLEMENTED
- Owner: dpone maintainers / Codex integrator
- Issue: implementation request approved by the maintainer on 2026-07-23
- Target release: next patches after 0.73.17; Studio UI 0.1.0
- Last verified: 2026-07-23
Approval¶
The maintainer approved the complete implementation plan on 2026-07-23. This specification is the implementation contract for the core capability read model, correctness fixes, the local Studio API boundary, and the later read-only UI. It does not approve remote production hosting, SSO/RBAC, runtime execution from Studio, or a second authoring engine.
The core capability, CLI, Studio API, compatibility, and security scope is
implemented and validated in
test_artifacts/studio-capability-self-service-v1/validation.md. The separate
Studio UI release remains NO-GO until the commit-bound five-user usability
gate passes; implementation status does not manufacture that missing evidence.
Executive summary¶
dpone already has a five-command Airflow self-service path and a dpone studio
HTTP bridge. The current bridge is not safe or internally consistent enough to
be a public product:
- non-executed quality checks can report success;
- connector and route status differs between CLI, marketplace, docs, and Studio;
- Studio can call unsupported route combinations valid;
- the HTTP adapter permits unauthenticated non-loopback access and wildcard CORS;
- OpenAPI and error responses are not sufficient for a typed external client;
airflow explaincan combine a missing pipeline with unrelated active-cache diagnostics.
The change introduces one read-only CapabilityDiscoveryService, fixes
false-success behavior, makes all public projections delegate to the same
snapshot, hardens the bundled HTTP adapter as a local development boundary, and
provides versioned DTOs for a separate read-only Nuxt/Vue UI.
Success means that a first-time engineer can select a scaffoldable route, create a pipeline, check it, and preview an Airflow DAG in at most 15 minutes without writing Airflow Python. Unsupported, unverified, skipped, or stale capabilities must never appear successful or certified.
Personas and customer journey¶
| Persona | Goal | Current pain | Success signal |
|---|---|---|---|
| New data engineer | Pick a supported route and create a DAG | Matrix, recipes, and connector statuses disagree | One route projection and one exact next command |
| Data engineer | Diagnose one pipeline | Explain can mix global and target state | Target-scoped summary and structured recovery |
| Platform engineer | Expose safe local Studio | HTTP boundary is fail-open | Loopback-first, bounded, authenticated remote opt-in |
| Airflow operator | Understand support versus certification | Maturity and evidence are collapsed | Separate support, maturity, certification, evidence |
| UI developer | Build without duplicating dpone policy | OpenAPI is incomplete | Typed OpenAPI 3.1 and stable DTOs |
Beginner journey¶
dpone init project --airflow
dpone init pipeline orders_daily --route mssql:clickhouse:incremental_merge
dpone check orders_daily
dpone airflow preview orders_daily
dpone test orders_daily
--recipe remains compatible. When --route is omitted on an interactive
terminal, only scaffoldable routes are offered. A supported route without a
recipe remains visible but is labelled beginner_recipe_available: false.
The read-only Studio journey is:
route/recipe discovery
-> pipeline list
-> target-scoped pipeline summary
-> Airflow artifact state
-> structured diagnosis and recovery
Studio authoring is a later milestone and uses the existing confined scaffold plan/apply transaction rather than storing a second project model.
Scope¶
In scope¶
- Fail-closed managed quality outcomes.
- One connector/route/recipe capability snapshot and semantic digest.
- Additive recipe discovery filters and route metadata.
- Additive
init pipeline --routefacade. - Target-scoped Airflow explanation.
- Strict Studio draft/reconciliation input and route validation.
- Versioned read-only Studio API and complete OpenAPI 3.1.
- Loopback-first HTTP security, resource limits, audit ordering, and redaction.
- Compatibility aliases for current
/api/*routes and CLI JSON keys. - Honest Studio metadata when the UI is not installed.
- A separate read-only Nuxt/Vue UI after core API certification.
Non-goals¶
- A new manifest, recipe, route, certification, or runtime engine.
- A new top-level CLI command group.
- Drag-and-drop DAG authoring.
- Studio-triggered sample runs or credential resolution.
- Remote production hosting, SSO, or multi-role RBAC.
- Storing Vault paths, credentials, or project configuration in a Studio DB.
- Claiming every runtime-supported route has a beginner recipe.
- Treating missing live evidence as a pass.
Assumptions and constraints¶
- PR #437 is the required base and is present in master as
77f2b530. - YAML, declarative catalogs, and verified evidence remain authoritative.
- The bundled server remains stdlib-only for the first core release.
- Existing compatibility routes remain available for at least two minor releases and 12 months.
- Existing valid
--recipecommands and JSON keys remain accepted. apiis an endpoint family andrestis a provider identity; they are not collapsed into an undocumented alias.
Public contract¶
Capability discovery¶
The public DTO has schema dpone.capability-discovery.v1:
schema: dpone.capability-discovery.v1
snapshot_id: sha256:...
connectors:
- id: mssql
endpoint_types: [mssql]
roles: [source, sink]
install_extras: [mssql]
maturity: experimental
release_phase: beta
routes:
- id: mssql:clickhouse:incremental_merge
source: mssql
sink: clickhouse
strategy: incremental_merge
support:
status: supported
limitations: []
certification:
level: experimental
evidence_status: UNVERIFIED
evidence_ref: null
beginner:
recipe_refs: [mssql-to-clickhouse-incremental]
recipe_available: true
recipes:
- ref: mssql-to-clickhouse-incremental
source: mssql
sink: clickhouse
strategy: incremental_merge
Five axes remain independent:
| Axis | Vocabulary |
|---|---|
| Connector maturity | certified, experimental, community |
| Release phase | stable, beta, alpha |
| Route support | supported, conditional, not_supported |
| Route certification | experimental, route-certified, production-certified, enterprise-certified |
| Evidence | PASS, FAIL, SKIP, UNVERIFIED |
Missing, stale, malformed, mocked, skipped, foreign-commit, or unavailable
evidence yields UNVERIFIED. It cannot promote maturity or route
certification.
Credential-free mock_contract runs may report passed: true for their
behavioral assertions, but the report always carries
evidence_status: UNVERIFIED. Empty mock selections are passed: false.
Evidence bundles and go-live gates require both a passing report and
evidence_status: PASS; mock output can never satisfy that gate.
All certification-sensitive release and runtime readers use one typed
certification-trust predicate, including release summary, promotion,
change-request, post-deploy, production maturity, evidence packs, and native
transfer route activation. A certification payload without evidence_status,
including a legacy payload with passed: true, is UNVERIFIED; generic
evidence keeps its historical evaluation rules unless it declares an evidence
status. Static native-transfer planning can expose
behavior_passed: true, but it always returns passed: false and
evidence_status: UNVERIFIED until approved current live evidence exists.
Exact uppercase PASS is necessary but not sufficient: non-empty blockers,
violations, findings, errors, failed required stages, a mismatched release, or
a changed or missing stage artifact fail closed. Operational bundles are
non-vacuous, required names are unique, and consumers re-read each JSON file
and compare its recorded SHA-256 before a go-live decision. A stage or bundle
cannot become trusted by copying passed: true and evidence_status: PASS.
Fixture-driven CDC apply, performance threshold, route capability, and
live-state aggregation reports expose behavioral success separately and remain
UNVERIFIED until a current approved live proof supplies authority.
Public composition roots load optional evidence only from the explicit,
bounded capability_discovery.certification_evidence section in dpone.yaml.
The section pins one matrix path, one expected commit, a bounded list of proof
directories, and a freshness limit. No CLI, Studio, or marketplace surface
recursively discovers certification artifacts.
Certification candidates are derived from the validated canonical matrix rows
and injected into the proof reader; the generic discovery boundary does not
import a connector-specific safe-sample catalog.
snapshot_id is the SHA-256 of deterministic canonical JSON excluding volatile
timestamps. Connector, route, and recipe lists are sorted by logical identity.
Quality¶
Managed quality outcomes use passed | failed | skipped | unverified.
Compatibility serializers may retain legacy pass | fail | skip values only
when the semantic result is unchanged.
executed pass -> passed
executed failure -> failed
mode=skip -> skipped
plan-only/live-miss -> unverified
empty run -> unverified
Aggregate passed is true only when at least one check executed and every
configured check is passed or non-blocking warning. Empty, all-skipped, or any
unverified run has passed: false.
CLI¶
dpone recipe list [--source TYPE] [--sink TYPE] [--strategy MODE]
dpone recipe show REF
dpone init pipeline ID (--recipe REF | --route SOURCE:SINK:STRATEGY)
dpone connectors certify [--report-only]
- Recipe list/show output adds route, support, evidence, install-extra, limitations, and next-command fields.
- Filtered list output also includes matched
routes[]; a supported route with no recipe remains visible withbeginner.recipe_available: false. - Capability authority errors are returned as
passed: falseplusissues[]and a non-zero exit instead of being hidden behindUNVERIFIED. - A malformed external recipe catalog is represented as a stable capability issue; built-in recipes remain discoverable, but every consuming CLI, Studio, marketplace, and evidence surface remains non-passing.
- Existing fields are not removed.
--routeand--recipeare mutually exclusive.- Non-interactive invocation without either keeps the existing default recipe.
- Interactive invocation may present a bounded picker of scaffoldable routes.
- Unknown or non-scaffoldable routes fail before filesystem writes with
DPONE_ROUTE_NOT_SUPPORTEDorDPONE_ROUTE_NOT_SCAFFOLDABLE. - Explicit
--recipeselection resolves through the same capability authority before filesystem writes. A recipe whose declared route is absent ornot_supportedis projected as non-scaffoldable and fails closed. connectors certifyexits1whenpassed=false;--report-onlyexplicitly preserves report-only exit0.--fail-on-missingremains accepted with one deprecation warning per process.- Self-service and discovery result payloads are written to stdout, including
structured
passed: falseresults, preserving the established automation contract. Parser/usage diagnostics and fatal Studio startup errors are written to stderr.
Pipeline summary¶
dpone.pipeline-summary.v1 is target-scoped:
schema: dpone.pipeline-summary.v1
id: orders_daily
source_path: pipelines/orders_daily/pipeline.yaml
valid: true
operational_status: ready
authoring_mode: flow
recipe: mssql-to-clickhouse-incremental
processes:
- name: orders_daily
source: mssql
sink: clickhouse
strategy: incremental_merge
quality_gates: []
schedule: null
artifact_state: {}
support: {}
certification: {}
next_actions: []
errors: []
Every declared process must resolve to a supported canonical route. An unknown
or not_supported route makes the summary valid: false,
operational_status: blocked, adds DPONE_ROUTE_NOT_SUPPORTED, and replaces
Airflow preview guidance with dpone check.
Processes retain canonical source order. A missing pipeline cannot inherit materialized, pinned, or runtime-delivery status from another pipeline.
Studio API¶
Canonical routes:
GET /healthz
GET /openapi.json
GET /api/v1/meta
GET /api/v1/capabilities
GET /api/v1/recipes
GET /api/v1/pipelines
GET /api/v1/pipelines/{id}/explain
POST /api/v1/manifests/draft
POST /api/v1/plans
POST /api/v1/checks/static
The API is read-only with respect to durable project state. POST is used for bounded query payloads, not mutation.
GET /api/v1/recipes returns the same snapshot_id, passed, and issues[]
authority state as CLI recipe discovery. Draft, canonical plan, deprecated plan
alias, inline static check, and pipeline-referenced static check all use one
injected route validator. Plan and static-check compile the authoring source
once, resolve classic table overrides, and validate the same resolved
ProcessSpec snapshot consumed by planning. A complete effective route absent
from the snapshot fails with DPONE_ROUTE_NOT_SUPPORTED before a plan can
report success. Effective certification-artifact references are read only from
those canonical objects, must resolve to bounded regular files inside the
project root, and cannot escape through .. or symlinks.
All errors use dpone.error.v1. HTTP mapping is:
| Condition | Status |
|---|---|
| malformed JSON | 400 |
| missing/invalid token | 401 |
| forbidden origin or policy | 403 |
| unknown route | 404 |
| wrong method | 405 |
| request timeout | 408 |
| body over limit | 413 |
| unsupported media type | 415 |
| schema/domain validation | 422 |
| rate/concurrency boundary | 429 |
| redacted internal failure | 500 |
Existing /api/* routes are deprecated aliases. Where legacy behavior was
unsafe, the alias returns a fail-closed result rather than preserving false
success. Aliases emit Deprecation, Sunset, and Link headers and remain
for at least two minor releases and 12 months. The earliest planned removal
date is 2027-07-23.
HTTP boundary¶
Defaults:
host: 127.0.0.1
body_limit_bytes: 1048576
request_timeout_seconds: 10
max_concurrent_requests: 32
audit_capacity: 1000
page_size_default: 100
page_size_max: 200
cors: same-origin
Non-loopback bind requires all of:
--allow-remote;- a non-empty token;
- one or more exact allowed origins.
Failure occurs before bind with CLI exit code 4. Tokens are compared in
constant time. RBAC is not advertised; this milestone provides one shared-token
identity only.
Paths are resolved under the configured project root with bounded, no-follow reads and symlink-escape checks. API output never contains shell command strings assembled from user input; command suggestions are structured argv.
Studio UI¶
After core API certification, the separate PaulKov/dpone-studio project will
use Nuxt 4, Vue, TypeScript, Node 22+, generated OpenAPI types, Vitest, and
Playwright. No public UI repository or release is claimed by the core patch.
UI 0.1.0 is read-only and contains route/recipe discovery, pipeline details,
Airflow artifact state, and structured diagnostics.
The UI owns presentation only. It does not maintain capability tables, parse
CLI output, compile manifests, resolve credentials, or decide certification.
The primary local topology serves versioned static assets from the same origin.
Without compatible assets, metadata reports ui_status: not_installed.
Asset installation is not a product-readiness decision: metadata independently
reports usability_status: UNVERIFIED and release_verdict: NO-GO until
commit-bound five-user evidence is approved.
Detailed algorithms¶
Capability snapshot¶
at the start of each CLI command or Studio use case:
load import-safe connector declarations
load static route profiles and strategies
load recipe catalog
load optional certification evidence through strict validator
evaluate freshness against the injected trusted clock
normalize endpoint family and provider identity explicitly
for each declared connector:
project roles, extras, maturity, release phase
for each route profile:
project support and limitations
attach exact matching recipes
attach certification only when evidence identity is current and valid
sort all collections by logical identity
canonicalize non-volatile payload
compute snapshot_id
return immutable DTO
Discovery performs no network, database, secret, runtime, or Airflow metadata calls. A long-lived Studio captures exactly one snapshot per use case rather than retaining a process-lifetime snapshot.
Managed quality¶
validate rows and checks as bounded mappings
if checks is empty:
return aggregate unverified, passed=false
for each check:
if mode=skip:
outcome=skipped
elif check requires live context and no exact live evidence:
outcome=unverified
else:
execute check and return passed/failed
preserve advisory behavior in mode=warn, not a fifth status
aggregate passed only when executed_count > 0
and failed_count == 0
and unverified_count == 0
and skipped_count < configured_count
HTTP request¶
reject non-loopback unsafe configuration before bind
acquire bounded concurrency slot or return 429
parse route and exact origin
authorize with constant-time token comparison
validate method, media type, content length, JSON, and request schema
invoke injected application service
map typed domain error to dpone.error.v1 and HTTP status
record exactly one redacted audit event
send exact-origin CORS only when allowed
release concurrency slot
Studio authoring v0.2¶
request route/recipe and logical connection refs
compile existing scaffold plan
return unified diff + source fingerprints + plan_digest
apply requires plan_digest + expected fingerprints + idempotency key
lock project transaction
re-read sources and recompute plan
reject fingerprint or digest mismatch
apply through existing atomic scaffold applier
persist rollback journal and idempotent receipt
never modify credentials, runtime, release, or deployment state
Architecture¶
| Component | Responsibility | Dependencies |
|---|---|---|
CapabilityDiscoveryService |
Immutable connector/route/recipe projection | Explicit catalog/evidence ports |
PipelineSummaryService |
Target-scoped authoring/Airflow summary | Compiler, explain snapshot, capabilities |
| CLI facades | Parse/render only | Application services |
StudioApplicationService |
Strict-DI read-only use-case facade | Snapshot provider and injected application services |
StudioApiService |
Deprecated zero-argument Python compatibility facade | Studio composition root |
| HTTP adapter | Bounded transport, auth, CORS, errors, audit | Studio API protocols |
| Studio UI | Presentation and browser state | Generated API client |
Composition occurs in the dpone.readiness application composition modules or
thin command composition roots. Services do not instantiate vendor clients or
call private methods on other services.
Marketplace, readiness certification, and legacy Studio catalog functions
become delegating compatibility views.
Alternatives and tradeoffs¶
| Alternative | Decision |
|---|---|
| Keep static lists in each facade | Reject: contradictory status and DRY violation |
One generic status |
Reject: hides support/evidence semantics |
| UI owns its own catalog | Reject: second policy engine |
| Add FastAPI immediately | Defer: unnecessary dependency for local adapter |
| Bundle a DAG canvas | Reject for v1: another authoring surface |
| Read-only UI before authoring | Adopt: validates API and user model safely |
ADR requirement¶
ADR 0030 is required because authority, dependency direction, external API versioning, evidence semantics, and the local/remote HTTP boundary are cross-layer architectural decisions.
Quality-budget impact¶
New domain/read-model modules stay under the repository max_sloc: 400 hard
limit. HTTP routing, request parsing, security policy, audit storage, OpenAPI,
and service composition are separate responsibilities. No generic plugin
system is introduced. Existing clustering and layer budgets may not regress.
Market comparison¶
Primary official sources verified 2026-07-23.
| System | Observed pattern | Decision | Source |
|---|---|---|---|
| Airbyte Connector Builder | UI and direct YAML represent the same declarative model with validation | Adopt one authoring authority; reject hidden UI state | https://docs.airbyte.com/platform/connector-development/connector-builder-ui/overview |
| dltHub 1.29 | Local dashboard exposes metadata, traces, history, schema, and state | Adopt local read-only operational view | https://dlthub.com/docs/hub/ingestion/dashboard |
| Fivetran | Connection list separates source, destination, status, and troubleshooting | Adopt concise filtering and status explanation | https://fivetran.com/docs/getting-started/fivetran-dashboard/connectors |
| Astronomer Cosmos | Static project artifacts materialize Airflow DAG/TaskGroup objects | Adopt static orchestration boundary only; N/A for Studio UI | https://astronomer.github.io/astronomer-cosmos/getting_started/core-concepts.html |
| Microsoft SSIS | Visual control/data-flow designer and connection managers | Reject drag/drop in v1; it creates opaque parallel authoring | https://learn.microsoft.com/en-us/sql/integration-services/ssis-designer |
| Informatica | N/A for this local open API boundary | No directly adopted pattern | N/A |
| Pentaho | N/A for parse-safe Airflow self-service | No directly adopted pattern | N/A |
| gusty | N/A for capability/Studio design | No directly adopted pattern | N/A |
| Apache Beam | N/A for authoring UI and connector certification | No directly adopted pattern | N/A |
Measurable differentiation¶
axis: time to a correctly diagnosed first Airflow DAG
scenario: first-time engineer selects a scaffoldable route and previews its DAG
baseline: capability surfaces disagree; human result is UNVERIFIED
metric: completion time and facilitator actions
target: ">=80% of at least 5 users finish within 15 minutes with 0 facilitator actions"
procedure: scripted fresh-project usability session plus telemetry-free observer scorecard
artifact: test_artifacts/studio-usability/<date>-<commit>/{usability-study.json,certification.json,certification.md,summary.md}
limitations: route sample begins with built-in scaffoldable routes
Security, privacy, and operations¶
- No secrets or Vault paths in capability, summary, OpenAPI, logs, or audit.
- Shared tokens are read from environment/configuration and never echoed.
- Remote binding requires an explicit policy and is still development-only.
- Registry/evidence paths are redacted for non-platform views.
- Audit is process-local, bounded, synchronized, and explicitly non-durable.
- Read-only endpoints do not trigger live connector probes by default.
- Runs/artifact listing is confined, paginated, bounded, and race-safe.
- UI stores token in memory/session only, never durable browser storage.
Test and certification plan¶
| Layer | Scenario | Environment | Expected artifact |
|---|---|---|---|
| Unit | quality truth table and validators | hermetic | pytest report |
| Contract | capability parity and schemas | hermetic | snapshot/parity JSON |
| Contract | HTTP/OpenAPI error and security matrix | loopback with fakes | JUnit + OpenAPI validation |
| Integration | 100 concurrent requests and bounded runs | local mocked | load-boundary report |
| Compatibility | legacy CLI/API aliases | hermetic | compatibility matrix |
| UI | route/pipeline/diagnosis workflows | Playwright desktop/mobile | screenshots + JUnit |
| Live | remote boundary and exact connector evidence | approved environment only | PASS/FAIL/SKIP evidence |
| Usability | first-time five-command path | at least 5 new users | scorecard |
Required negative cases include malformed JSON, oversized/slow body, wildcard or
null origin, missing token, path traversal, symlink escape, shell
metacharacters, stale/mock evidence, unknown route, duplicate identities,
source mutation between plan/apply, malformed recipe authority on every
projection, mock evidence presented to a go-live gate, and injected internal
failures. The matrix also covers status-less and UNVERIFIED certification at
every release/runtime consumer, static native-transfer evidence, effective
classic overrides, and explicit unsupported external recipes before writes.
Release-chain coverage additionally includes bundle replay across releases,
forged artifact indexes, missing or tampered stage files, empty bundles,
duplicate required evidence, contradictory PASS payloads, and unsafe retry
claims attached to failed certification evidence. Release summaries require
the latest chain entry and every certification suite to match the requested
release; the chain's immutable artifact index must exist, match its recorded
digest, and contain the exact suite digest. Every release-bound index item is
reread through bounded regular-file checks and its SHA-256 is recomputed,
including replay chains without a separately named suite. Duplicate logical
names or paths, traversal, symlinks, missing files, and digest drift fail
closed.
Documentation plan¶
- Update the First DAG and recipe reference with route-aware discovery.
- Add a curated beginner command index; keep generated CLI reference generated.
- Correct Studio documentation to distinguish API bridge, optional assets, and not-yet-supported remote production use.
- Add capability DTO, OpenAPI, security, compatibility, and troubleshooting references.
- Keep matrix rows explicit about beginner recipe availability.
- Remove stale image/version examples and unimplemented RBAC claims.
Rollout and rollback¶
- Correct false-success and target-scope bugs.
- Introduce capability service and migrate all projections.
- Publish versioned schemas and hardened local API.
- Certify CLI/API parity and security gates.
- Run the human usability gate for the exact release candidate.
- Release read-only UI 0.1.0 only after the gate passes.
- Design and release authoring UI 0.2.0 under a separate approved milestone.
Rollback retains legacy aliases and can disable the versioned Studio server without reverting capability truth fixes. A certification or quality false-positive is an immediate rollback/release-blocking condition.
Agent execution plan¶
| Role | Owned paths | Forbidden paths |
|---|---|---|
| Architect reviewer | read-only architecture and contracts | all writes |
| Correctness implementer | managed quality and focused tests | shared schemas/docs |
| Capability implementer | capability service and focused tests | CLI/docs/shared registries |
| HTTP implementer | Studio HTTP adapter and focused tests | capability authority/docs |
| Integrator | shared schemas, CLI, docs, changelog, composition | none |
| Fresh reviewer | read-only final diff and evidence | all writes |
The integrator owns shared schemas, registries, CLI composition, MkDocs,
CHANGELOG.md, and final evidence.
Approval checklist¶
- User problem and CJM are clear.
- Algorithm and failure semantics are implementable without guessing.
- Public contracts and compatibility are explicit.
- Architecture and alternatives are justified.
- Market research uses current official primary sources.
- Claimed differentiation is measurable.
- Tests, evidence, docs, rollout, and rollback are complete.
- Path ownership and integration plan are conflict-safe.
- Maintainer approved implementation on 2026-07-23.