Skip to content

ADR-001: Use Datalab as the Public Contract

Status

Accepted

Date

2026-06-20

Implementation

Implemented.

Users create a Datalab. Provider Datalab turns it into a working data workspace and reports session information on the same resource.

Educates is the core runtime used by the current implementation. Its resources are created and managed internally; users and client tools do not need to know about them.

Educates also provides the browser editor and terminal.

Context

A data workspace needs many things: an editor, a terminal, persistent files, credentials, networking, and optional services. Exposing every resource needed to build that workspace would give users a complicated and fragile API.

We need one stable contract that describes what a user wants, while allowing the implementation behind it to change.

Decision

Make Datalab the only public workspace resource

Users and GitOps tools work with the namespaced Datalab resource. It describes the desired workspace, including its named sessions and optional capabilities.

The Datalab name, namespace, and UID form its stable identity. Generated Pod, Secret, and runtime-resource names are not part of the public contract.

Use Educates as the internal runtime primitive

Educates provides the editor, terminal, workspace Pod, session runtime, and optional applications. Crossplane translates a Datalab into the Educates and Kubernetes resources required to run it.

This translation is an implementation detail:

User or GitOps tool
  -> Datalab
     -> Provider Datalab reconciliation
        -> internal runtime resources
           -> working Datalab session

Clients never create, update, discover, or depend on Educates resources directly. Crossplane owns those generated resources. This keeps one source of truth and lets the runtime implementation evolve without changing how users manage a Datalab.

The same rule applies if the internal runtime changes later. Runtime resources remain projections of the Datalab and do not become a second public workspace API.

Keep user choices separate from operator policy

The Datalab spec contains choices that a user is allowed to make. The operator-owned EnvironmentConfig contains platform settings such as ingress, Keycloak realm, storage classes, security defaults, and extension packages.

Crossplane combines both sets of input. Users therefore get a small API, while operators keep control of security and infrastructure policy.

Manage sessions through the Datalab

Each session has a unique name and a desired state such as started or stopped. Provider Datalab creates the internal runtime for started sessions and reports the observed phase, message, and browser URL in Datalab.status.sessions.

Clients read the Datalab status. They do not look up the internal runtime. Diagnostic phase and message text is not a stable machine-readable lifecycle API; richer clients will need typed status fields.

The current API does not have a separate environment or profile object. Add such concepts only through a separate decision and a compatible API change.

Keep credentials out of the API

Credentials are read from referenced Kubernetes Secrets and copied only where the runtime needs them. Secret values never belong in the Datalab spec, status, logs, or normal client output.

Credentials and security settings currently apply to the whole Datalab. Use separate Datalabs when workloads need separate Kubernetes control planes or a stronger trust boundary.

Add tools without changing the contract

Operators can add runtime tools through extension packages. This keeps the Datalab API stable and avoids baking every tool into one large base image.

Why This Design

Design choice Reason
One Datalab API Users have one clear object to create, review, and manage.
Educates stays internal Clients are not coupled to runtime-specific resources or names.
Access runtime stays internal The access implementation can change without creating a second user API.
Crossplane owns generated resources Reconciliation has one owner and does not compete with user changes.
User input and operator policy are separate Self-service does not bypass platform security or infrastructure rules.
Status is copied to the Datalab Clients do not need broad access to internal resources.
Credentials stay in Secrets The public API does not become a credential-delivery channel.

Consequences

  • Provider Datalab is self-contained: clients need only the Datalab API.
  • Educates is essential to the current implementation but is not part of the client contract.
  • Changing the internal runtime does not require a second public workspace model.
  • Crossplane remains responsible for generated-resource ownership and cleanup.
  • Operators must validate user-selectable Secret references and other policy-sensitive options.
  • Some lifecycle behavior still needs live transition tests.