Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3fdf4f8
docs(sdd): specify issue contract in specs/platform-foundation-identi…
github-actions[bot] Oct 31, 2026
95458b8
feat: add tested transactional SQLite storage kernel
efraespada Oct 31, 2026
53cbd4d
feat: add identity policy, local authorization and session leases
efraespada Oct 31, 2026
16999cd
feat: add bounded Home Assistant identity protocol adapters
efraespada Oct 31, 2026
780281e
feat: add standalone Home Assistant authentication runtime
efraespada Oct 31, 2026
98bd12f
feat: add native Home Assistant Ingress authentication preview
efraespada Oct 31, 2026
650f151
feat: package the native HA Edge preview with container CI
efraespada Oct 31, 2026
146b984
feat: add atomic household setup and enrollment commands
efraespada Oct 31, 2026
508d414
feat: guard member administration with current HA authority
efraespada Oct 31, 2026
16f28de
feat: preserve administrator provenance in household policy edits
efraespada Oct 31, 2026
4646ee1
feat: expose household API with persistent standalone composition
efraespada Oct 31, 2026
d1571d0
feat: wire persistent native household API and bounded Ingress sessions
efraespada Oct 31, 2026
ddc90fa
feat: persist owned installation identity and exclusive data lifecycle
efraespada Oct 31, 2026
58d88fa
feat: add console-approved administrator recovery with atomic consump…
efraespada Oct 31, 2026
f922051
feat: create and inspect consistent private SQLite snapshots
efraespada Oct 31, 2026
48c06bf
fix: reject owned databases from explicit-file runtime paths
efraespada Oct 31, 2026
78766a0
feat: share managed data lifecycle with standalone runtime
efraespada Oct 31, 2026
d013cf2
feat: prepare private Home Assistant app launcher
efraespada Oct 31, 2026
fcbf786
feat: package persistent native Home Assistant runtime
efraespada Oct 31, 2026
47a0f24
test: record persistent HA acceptance and restore history policy
efraespada Oct 31, 2026
03e5e82
feat: prepare blocked SQLite restoration with retained history
efraespada Oct 31, 2026
002a982
fix: enforce restoration inspection completion deadline
efraespada Oct 31, 2026
5ac4da7
feat: retain restored operation history and recovery guards
efraespada Oct 31, 2026
0e86193
feat: load bound storage generations and block partial restores
efraespada Oct 31, 2026
faa1654
feat: activate and resume verified offline restorations
efraespada Oct 31, 2026
d9e5a90
feat: package verified restoration with previous-image compatibility
efraespada Oct 31, 2026
0484ba7
docs: refresh catalog for restoration package evidence
efraespada Oct 31, 2026
8b59a04
docs: record Edge.3 owner update and session acceptance
efraespada Oct 31, 2026
ead7dde
fix: explain membership access and trace foundation acceptance
efraespada Oct 31, 2026
9c44195
docs: correct current snapshot capture schema
efraespada Oct 31, 2026
d67475a
docs: preserve full clarification evidence for complete review
efraespada Oct 31, 2026
e26a1e6
fix: address browser origin and recovery review regressions
efraespada Oct 31, 2026
4505d82
fix: canonicalize IPv6 browser origins
efraespada Oct 31, 2026
72e3e87
docs: bind historical evidence to its verified source commits
efraespada Oct 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion .github/workflows/ci_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,33 @@ jobs:
if-no-files-found: error
retention-days: 7

backend:
name: Backend application
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
with:
version: "0.11.29"
enable-cache: false
- run: uv sync --frozen
- run: uv run mypy backend/src
- name: Test every authored backend module with separate coverage
run: uv run pytest tests/backend --cov=domus --cov-branch --cov-report=term-missing --cov-report=json:coverage-backend.json --cov-report=xml:coverage-backend.xml
- name: Retain backend coverage
if: ${{ always() }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: backend-coverage-${{ github.sha }}
path: |
coverage-backend.json
coverage-backend.xml
if-no-files-found: error
retention-days: 7

node:
name: Node architecture policy
runs-on: ubuntu-latest
Expand Down Expand Up @@ -83,6 +110,7 @@ jobs:
enable-cache: false
- run: uv sync --frozen
- run: uv run lint-imports --config architecture/python-tooling.ini --no-cache
- run: uv run lint-imports --config architecture/python-application.ini --no-cache
- run: uv run pytest tests/architecture

documentation:
Expand All @@ -100,10 +128,46 @@ jobs:
- run: uv sync --frozen --no-dev
- run: uv run --no-dev domus-check docs

containers:
name: App container (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-latest
arch: amd64
- runner: ubuntu-24.04-arm
arch: aarch64
runs-on: ${{ matrix.runner }}
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
with:
version: "0.11.29"
enable-cache: false
- run: uv sync --frozen
- name: Build the exact Supervisor app folder
run: docker build --build-arg BUILD_ARCH=${{ matrix.arch }} -t domus-app-ci addon-edge
- name: Build the immutable previous image for upgrade and downgrade checks
run: >-
docker build --build-arg BUILD_ARCH=${{ matrix.arch }}
--build-arg BUILD_VERSION=0.0.0-edge.2
--build-arg DOMUS_SOURCE_COMMIT=d013cf2c8b932d0e00f5858053cbc0e663d5eee1
--build-arg DOMUS_SOURCE_SHA256=fa58d457bef8a863a1943b4e6ba5c9513da8d3baa8b0a033bdcbe7bf11b09c6c
-t domus-app-previous addon-edge
- name: Verify the real image, listener and cleanup
env:
DOMUS_TEST_IMAGE: domus-app-ci
DOMUS_PREVIOUS_IMAGE: domus-app-previous
run: uv run pytest tests/containers --no-cov

aggregate:
name: CI Check
if: ${{ always() }}
needs: [python, node, architecture, documentation]
needs: [python, backend, node, architecture, documentation, containers]
runs-on: ubuntu-latest
timeout-minutes: 10
env:
Expand Down
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ into one responsive interface. Normal operation does not require AI or cloud ser

## Project status

Domus has started its development-tooling foundation. No household application is implemented or published yet.
Domus has tested backend storage, identity policy and a standalone authentication API/CLI in development.
A stateless Edge HA app preview now uses native Ingress authentication without another sign-in.
The household product, product UI, production packages and release artifacts remain incomplete.
The [documentation foundation issue](https://github.com/vypdev/domus/issues/2)
tracks eleven Draft SDDs, 82 normative requirements and 353 planned acceptance cases.
These cases are verification plans, not executed application tests.
The M1 identity/storage companion adds its own 61-case plan; partial backend evidence does not complete it.

The first usable release covers all six domains, Supervisor App/Ingress and
standalone Container, and isolated Stable and experimental Edge channels.
Expand All @@ -38,12 +41,16 @@ in the application, with the chosen policy and actual awards preserved in the le
- [Acceptance, coverage and CI Check plan](docs/acceptance-plan.md)
- [Specification validation evidence and limitations](docs/sdd-validation.md)
- [Development setup, tests and CI Check](docs/development.md)
- [Home Assistant app installation and development preview](docs/installation-home-assistant.md)
- [Implemented authentication journey and limits](docs/identity-household.md)
- [Authentication server configuration](docs/configuration.md)
- [Identity/storage operations and pending commands](docs/operations-identity-storage.md)

## Quality and contribution

Clean Architecture is mandatory. Meaningful tests accompany every implementation
from its first change, with 100% supported first-party coverage metrics as the
required implementation gate. A future project-owned workflow named **CI Check** runs
required implementation gate. The project-owned workflow named **CI Check** runs
the full applicable suite for every PR update. English is used for issues,
documentation, source identifiers and comments; the product supports English and Spanish.

Expand All @@ -60,13 +67,15 @@ preparation when necessary. Merge, release and deployment remain separately auth
## Readiness limitations

All SDDs remain Draft while material decisions are reviewed. Their original Copilot
format and consistency checks pass. The proposed SDK catalog still fails the unchanged
upstream evidence validator for the ten capabilities without implementation. Delivery-quality
registers only its real partial tooling/CI evidence; no fake paths or gate-readiness claims are used. See the
format and consistency checks pass. The corrected upstream catalog validator accepts truthful
proposed capabilities with empty implementation arrays. Platform, identity and delivery-quality
register only their real partial evidence; no fake paths or gate-readiness claims are used. See the
[adoption note](docs/copilot-adoption.md).

The supplied brief ends at the beginning of section 10.2. The owner completed the
barcode scope on 2026-10-29: camera/manual entry, local matching and optional Internet
product lookup. Provider feasibility and device evidence still require review.
The initial tooling/tests and a separate CI Check workflow are now implemented; see the development guide.
Household application, UI and HA runtime tests remain future implementation work.
Complete household commands, UI, console recovery, snapshots, Supervisor session/listener wiring
and live/package acceptance remain pending. The authentication checkpoint uses real adapters and
offline provider/loopback fixtures; it is not a completed or published household release.
26 changes: 26 additions & 0 deletions addon-edge/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Changelog

## 0.0.0-edge.3

- Preserve complete original operation history separately from restored household state in SQLite schema 4.
- Add console-only restore preparation, verification, activation, status and interruption recovery.
- Retain a verified pre-activation source checkpoint; rollback also preserves newer replay evidence.
- Migrate only a verified target during restoration and retain original source data.
- Prevent reusing consumed or canceled recovery approval after restoring an older checkpoint.
- Mark the schema/history boundary as breaking: an older image must not open schema 4 or selected generations.
- Keep the complete product UI, live restore and production acceptance pending.

## 0.0.0-edge.2

- Add private persistent installation identity and SQLite household/member/policy/recovery services.
- Prepare only the app's own private data child, then run the server without root privileges.
- Require one to four fixed Home Assistant browser origins in the app configuration.
- Preserve data and original-operation receipts on restart; keep sessions in memory.
- Include manual snapshot creation/inspection and console-only recovery approval; restore remains pending.
- Keep the full household UI and production acceptance pending.

## 0.0.0-edge.1

- Add the native Home Assistant authentication preview without an additional sign-in.
- Bind the locally built app to reviewed runtime source and locked dependencies.
- Keep household commands, product UI and production acceptance explicitly pending.
43 changes: 43 additions & 0 deletions addon-edge/DOCS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Installation and operation

Install Domus Edge from the reviewed Domus development repository. In Configuration, set
public_origins to the URLs used to open HA, for example http://homeassistant.local:8123. Enter one to
four distinct origins without paths, credentials, queries or fragments, then start and select Open Web UI.
No password, copied token, OAuth callback or host port configuration is needed. The first installation
builds the reviewed runtime from an immutable source commit and frozen dependencies; allow the build
to finish before opening the UI.

The preview shows whether the current human can be verified through HA. It creates one private
installation identity and SQLite schema, retaining both across restart/update. It never implicitly
creates a household or member. The household/member/policy APIs and console-approved recovery are
included; the product UI is still a connection page. Existing sessions have bounded local read access
during HA outages; writes require fresh proof. Failure never grants default administrator access.

The container requests Core API access to verify individual HA users. HA grants this technical
connection administrator privileges, which the app never treats as the human's permissions.
It requests no Supervisor management API, host port, host network, privileged capabilities, devices
or host-directory mounts. A short container-root launcher prepares only /data/domus and then clears
supplementary groups and executes the server as UID/GID 65532. Existing data must already have the
correct private ownership/mode; there is no recursive repair or root server fallback. Domus reads the Supervisor-provided
credential into private runtime memory and does not write it into its web page, logs or business
storage. HA/Supervisor owns provisioning and the credential's platform lifecycle.

Stop the app to close its local sessions and release storage locks. Household records and original
operation receipts remain in /data/domus. Do not remove the installation marker, copy SQLite alone
or share this data with Stable. Edge.3 includes console-only restoration to a new verified generation;
it preserves later operation evidence without reapplying rolled-away effects. Stop the app before
restore preparation/activation. Inspect and resume the same activation ID after an uncertain result.
The retained source-checkpoint supports deliberate rollback reconciled against the latest history.
Do not switch root pointers or run an older image manually. See the
[restoration guide](https://github.com/vypdev/domus/blob/feature/6-implement-home-assistant-identity-and-sqlite-platform-persistence/docs/restoration.md)
for the exact console commands. Restore is not available from the connection page.
App removal with data
deletion removes the app's private records; use deliberate operator backup procedures before removal.
Changing public_origins requires a restart. Edge.2 and Edge.3 are marked as breaking versions so an
unattended update cannot cross their configuration and schema/history boundaries. Schema 4 refuses
downgrade by Edge.2; recovery requires a compatible image/data checkpoint pair.

Stopping does not sign out your HA frontend. There is no Domus OAuth
grant to revoke for this native mode. Remove the development app/repository after its owned test;
do not migrate production household data into this preview. A stable package will be published
separately when its acceptance gates pass.
30 changes: 30 additions & 0 deletions addon-edge/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# The Supervisor builds this folder. Fetch only the reviewed immutable runtime.
FROM ghcr.io/astral-sh/uv:0.11.29@sha256:eb2843a1e56fd9e30c7276ce1a52cba86e64c7b385f5e3279a0e08e02dd058fc AS uv
FROM python:3.14.6-slim-trixie@sha256:7bec7ddcddeff7975d6ba9b4be7dd6f6b2f55e7491539145e2978f7f97ce9144 AS builder
COPY --from=uv /uv /usr/local/bin/uv
ARG DOMUS_SOURCE_COMMIT=faa1654a5c9cddb562bfcd4c02d4cebfeb78e9f5
ARG DOMUS_SOURCE_SHA256=15bcd701696204b3362cebe5901feb3d0072c9bac1db2ef2cbc5007e9ed73717
ADD https://codeload.github.com/vypdev/domus/tar.gz/${DOMUS_SOURCE_COMMIT} /tmp/source.tar.gz
RUN printf '%s /tmp/source.tar.gz\n' "$DOMUS_SOURCE_SHA256" | sha256sum --check - \
&& mkdir /app \
&& tar --extract --gzip --file=/tmp/source.tar.gz --directory=/app --strip-components=1
WORKDIR /app
ENV UV_PYTHON_DOWNLOADS=never UV_NO_CACHE=1
RUN uv sync --frozen --no-dev --package domus-server --no-editable

FROM python:3.14.6-slim-trixie@sha256:7bec7ddcddeff7975d6ba9b4be7dd6f6b2f55e7491539145e2978f7f97ce9144
ARG BUILD_VERSION=0.0.0-edge.3
ARG BUILD_ARCH
ARG DOMUS_SOURCE_COMMIT=faa1654a5c9cddb562bfcd4c02d4cebfeb78e9f5
LABEL io.hass.type="app" \
io.hass.version="${BUILD_VERSION}" \
io.hass.arch="${BUILD_ARCH}" \
org.opencontainers.image.source="https://github.com/vypdev/domus" \
org.opencontainers.image.revision="${DOMUS_SOURCE_COMMIT}"
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:${PATH}" PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
# Only the fixed-path launcher provisions /data/domus as root; the server execs as 65532.
USER 0:0
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8099/health', timeout=3)"
ENTRYPOINT ["/app/.venv/bin/domus-ha-app", "--channel", "edge"]
11 changes: 11 additions & 0 deletions addon-edge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Domus Edge

Development preview of Domus installed as a Home Assistant app. Open it through HA's Open Web UI;
it uses your existing HA sign-in without another login.

Edge 0.0.0-edge.3 adds retained operation history and console-only restoration with interrupted
activation recovery. Private persistent identity, household APIs, bounded sessions and administrator
recovery remain included. The complete product UI remains under development. Set your Home Assistant browser
origins in the app's Configuration tab before starting. It remains experimental, with no stable release.

See [installation and permissions](DOCS.md).
30 changes: 30 additions & 0 deletions addon-edge/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Domus Edge
version: "0.0.0-edge.3"
slug: domus_edge
description: Development preview of the local Domus household application
url: https://github.com/vypdev/domus
arch:
- amd64
- aarch64
startup: application
boot: manual
stage: experimental
breaking_versions:
- "0.0.0-edge.2"
- "0.0.0-edge.3"
init: true
timeout: 30
ingress: true
ingress_port: 8099
panel_icon: mdi:home-heart
panel_title: Domus Edge
panel_admin: false
homeassistant_api: true
hassio_api: false
auth_api: false
ports: {}
options:
public_origins: []
schema:
public_origins:
- url
7 changes: 7 additions & 0 deletions addon-edge/translations/en.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
configuration:
public_origins:
name: Home Assistant browser origins
description: >-
The URLs used to open Home Assistant, including scheme and port when present,
for example http://homeassistant.local:8123. Enter one to four distinct origins
without paths. Restart Domus after changing them. Your existing HA sign-in is used.
11 changes: 11 additions & 0 deletions architecture/python-application.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,21 @@ forbidden_modules =
fastapi
homeassistant
httpx
httpx2
websockets
uvicorn
starlette
pydantic
requests
sqlite3
sqlalchemy
subprocess
asyncio
time
secrets
pathlib
os
fcntl

[importlinter:contract:no-cycles]
name = Application modules remain acyclic
Expand Down
24 changes: 24 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[project]
name = "domus-server"
version = "0.0.0"
description = "Local household application backend for Domus"
requires-python = ">=3.14,<3.15"
dependencies = [
"fastapi==0.162.0",
"httpx==0.28.1",
"uvicorn==0.54.0",
"websockets==17.4",
]

[project.scripts]
domus-server = "domus.composition.server:main"
domus-ingress = "domus.composition.ingress:main"
domus-admin = "domus.composition.admin:main"
domus-ha-app = "domus.composition.ha_app:main"

[build-system]
requires = ["hatchling==1.33.0"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/domus"]
1 change: 1 addition & 0 deletions backend/src/domus/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Domus household application, independent of its deployment adapters."""
1 change: 1 addition & 0 deletions backend/src/domus/application/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Use cases and semantic ports that depend only inward on domain contracts."""
Loading
Loading