Architecture¶
Caland follows a hexagonal / DDD design. Dependencies point inward, and all I/O sits behind domain ports, so the domain is fully unit-testable with no network.
src/caland/
domain/ model, rules + ports (SecretStore, WorkspaceConnector,
ProfileStore, BundleStore, SettingsStore)
application/ use-cases (WorkspaceService, OnboardingService, Loader),
the read model, and what reads a file somebody picked
infrastructure/ adapters — the ONLY place the Databricks SDK is imported
interface/web/ the page: a server on this machine, and what it serves
app.py the command: reads what was asked, wires it together
Layers¶
domain/— the model, rules, and ports. It imports nothing outward.application/— use-cases and a read model. A change to a workspace goes throughWorkspaceService, which takes one at a time and asks the workspace what is there now before it writes.infrastructure/— the adapters that implement the domain ports. This is the only place the Databricks SDK is imported, and the only code that writes~/.databrickscfg.interface/web/— the page.gate.pydecides which requests are answered at all — a pure function;server.pyanswers them;views.pysays what the page is told;static/is the page itself: one HTML file, one stylesheet, one script.app.py— the command.
The page never reaches the SDK
The boundary is strict: the browser talks to the server on your machine, the server to application services, application to domain ports, and only infrastructure/ reaches for the Databricks SDK or the network.
The page and the server¶
The page holds no secret and no name until it has been let in, and then only what it shows. Every request about a workspace carries the session's token and says which workspace it means; what a workspace says is written as text, never as markup. How it is kept yours has the rules, and spec/008-the-page.md in the repository the reasons.
Threading¶
The server answers each request on a thread of its own, and a workspace is read in the background, eight scopes at a time. Nothing blocks the page: it draws at once and fills as the workspace arrives.
Testing¶
Everything above infrastructure/ runs against in-memory fakes of the ports (tests/fakes.py). The server is asked over real HTTP, and the page is driven in a real browser — Chrome, over its debugging pipe (tests/chrome.py): real keys, real files, the real clipboard.