Compare commits
8
Commits
9c3b7c3735
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae4a4f0824 | ||
|
|
8d4aa87dd0 | ||
|
|
71aad7fc55 | ||
|
|
bd287a324a | ||
|
|
c671bf0bfe | ||
|
|
c9cd45e712 | ||
|
|
e887fcd435 | ||
|
|
98a9be3615 |
No files matched your search
@@ -11,12 +11,10 @@ and maintenance entry points. Global instructions remain applicable.
|
||||
environment, or access live company systems with write authority. Test writes need
|
||||
task-specific authority. Moving credentials or synchronizing company content
|
||||
requires agreement; ordinary repository work does not authorize either.
|
||||
- Follow the user's testing policy: automated tests only when explicitly requested
|
||||
or covered by an established repository policy. A test file alone does not establish
|
||||
a general policy. Use the smallest relevant review, build, or manual check.
|
||||
- Use `just validate` for a completed configuration batch, or name affected hosts
|
||||
for iteration. Read the short result first; inspect saved logs only for failures
|
||||
or a concrete unresolved concern. Documentation-only edits need no system build.
|
||||
- Do not write or run tests or perform extensive validation unless explicitly
|
||||
requested. For routine changes, use a focused review or small manual check.
|
||||
- Run `just validate` only when explicitly requested. Read its short result first;
|
||||
inspect saved logs only for failures or a concrete unresolved concern.
|
||||
- Replace superseded state in `docs/current-work.md`; keep durable rationale in
|
||||
`docs/design.md` and operational detail beside its owner. Use Git for chronology.
|
||||
Remove temporary state when it no longer serves a purpose.
|
||||
@@ -35,6 +35,10 @@ Both workstations import the provisional `work` profile. See
|
||||
company credentials and always-available read-only mounts. Only company-root and
|
||||
workbench environments are migrated; product/personal projects remain user-owned.
|
||||
|
||||
Orion's wardrobe service has its own
|
||||
[setup and operations guide](modules/capabilities/wardrowbe/README.md).
|
||||
Provision its SOPS secrets and two DNS records before building or activating Orion.
|
||||
|
||||
## Maintenance
|
||||
|
||||
```console
|
||||
@@ -55,9 +59,9 @@ directory. Failure stops the command; snapshots are removed on exit. It neither
|
||||
updates inputs nor creates result links or activates systems. The implementation is
|
||||
`scripts/validate.py`; `just` and Python are installed on both workstations.
|
||||
|
||||
Use targeted hosts during iteration and full validation for a completed batch.
|
||||
Documentation-only changes need review and `git diff --check`, not system builds.
|
||||
Build, activation and interactive behavior are separate evidence.
|
||||
Run targeted host builds or full validation only when explicitly requested. Routine
|
||||
changes need a focused review or small manual check. Build, activation and
|
||||
interactive behavior are separate evidence.
|
||||
|
||||
User-owned activation:
|
||||
|
||||
@@ -76,8 +80,8 @@ provisioning is documented with workbench. Never put plaintext secrets in Nix.
|
||||
- **Orientation:** Super+Shift+N names the focused workspace; submit an empty name
|
||||
to clear it. Named empty workspaces persist until cleared. Noctalia shows labels;
|
||||
terminal titles include the working directory and command.
|
||||
- **Icons/vault:** check Oil from Walker and Nautilus device/symbolic icons. Walker's
|
||||
`?` vault provider should request unlocking on use, never during desktop startup.
|
||||
- **Icons/vault:** check Oil from Walker and Nautilus device/symbolic icons. Check
|
||||
Walker's `?` vault provider; upstream Elephant may query `rbw` during startup.
|
||||
- **Calendar:** in Noctalia Settings → Services → Calendar, set the Radicale
|
||||
password through the existing Personal account (GNOME Keyring). Add an ICS account
|
||||
named Work using Outlook's published URL. Keep this URL in writable Noctalia
|
||||
|
||||
+48
-16
@@ -10,6 +10,7 @@ Complete independent agreed work and obvious fixes autonomously. Leave consequen
|
||||
unknowns pending and collect recommendations/alternatives into one substantial review
|
||||
batch. Ask earlier only to prevent broad rework/blockage. The old 2–4-question quota
|
||||
is superseded. Keep effort focused; no speculative systems or peripheral research.
|
||||
Do not write or run tests or perform extensive validation unless explicitly requested.
|
||||
Do not activate, push, decrypt for discovery or access company systems with write
|
||||
authority. No subagents unless explicitly authorized by current instructions.
|
||||
|
||||
@@ -17,6 +18,29 @@ Keep this record current by replacing superseded state. Pass-specific procedures
|
||||
stay here, not in AGENTS. The user must agree before the overall pass is complete.
|
||||
The unedited `~/sync/notes/setup-todo.md` remains an idea inbox, not authorization.
|
||||
|
||||
## Wardrowbe on Orion: implemented, awaiting provisioning and activation
|
||||
|
||||
- Orion selects the Wardrowbe capability at `wardrobe.jelles.net`, with Tinyauth
|
||||
password access at `wardrobe-auth.jelles.net`. Trusted household members select
|
||||
their profile through Wardrowbe's development login after the gateway; profile
|
||||
identity is not independently verified.
|
||||
- Podman containers use immutable image digests, a dedicated network and persistent
|
||||
named volumes. Database/queue health gates migrations and API startup; frontend
|
||||
and workers wait for the API. Caddy protects all application routes; published
|
||||
container ports are localhost-only. Internal AI is disabled everywhere. No
|
||||
Codex bridge, Ollama or paid provider is configured.
|
||||
- Four new system SOPS keys and both DNS records remain user-provisioned. Missing
|
||||
SOPS keys must be supplied before Orion builds or activates. See
|
||||
[Wardrowbe setup](../modules/capabilities/wardrowbe/README.md) for provisioning,
|
||||
activation, operations, upgrade limits and manual acceptance.
|
||||
- Focused source/configuration review only. No tests, host evaluation/build,
|
||||
`just validate`, activation or remote changes. No existing secrets were decrypted
|
||||
or read for discovery.
|
||||
- A user-run Orion build failed compiling Contour's SIMD code, pulled in by
|
||||
`enableAllTerminfo`. Orion now selects Kitty terminfo for workstation SSH clients
|
||||
instead of the complete terminal set. The pinned NixOS module was inspected;
|
||||
formatting and focused diff review only. No rebuild was run after this fix.
|
||||
|
||||
## Implemented, reviewed and validated; awaiting user checkpoint
|
||||
|
||||
- Flat capability owners; service category flattened. AI, theme, Handy and
|
||||
@@ -31,7 +55,7 @@ The unedited `~/sync/notes/setup-todo.md` remains an idea inbox, not authorizati
|
||||
Noctalia labels; shell titles include directory/command. Garden shell initialization
|
||||
now belongs to company integration instead of every host's generic shell.
|
||||
- Kanagawa declares Adwaita/hicolor icon fallback; modest Limine branding/layout.
|
||||
A pinned Elephant patch defers its startup `rbw list` to the explicit vault query.
|
||||
Walker uses upstream Elephant without a local vault patch. It may query `rbw` at startup.
|
||||
- GitHub devenv 2.3.2 installed with native Zsh hook and upstream reload defaults.
|
||||
CLI dependencies keep upstream pins/cache; workbench tools use this repository's
|
||||
exact nixpkgs pin. Company tools are also installed through the work profile. Product and
|
||||
@@ -53,6 +77,16 @@ The unedited `~/sync/notes/setup-todo.md` remains an idea inbox, not authorizati
|
||||
Validation prepares upstream devenv's import-from-derivation dependencies before
|
||||
read-only flake checking, accepts the repository's declared official cache, and
|
||||
reports interruption concisely. Full builds still include the tools-only shell.
|
||||
The devenv cache is now in persistent NixOS Nix settings; the flake cache hint
|
||||
was removed.
|
||||
- Noctalia tracks upstream's `cachix` branch with its own nixpkgs pin; persistent
|
||||
Nix settings include the official cache and signing key. The existing 5.2.1
|
||||
commit is unchanged. Its resulting x86_64 package has a matching signed cache
|
||||
entry; the previous package with our nixpkgs pin returned 404. No build or
|
||||
activation was run. For the first activation, pass the cache URL and key from
|
||||
`modules/capabilities/nix.nix` as `extra-substituters` and
|
||||
`extra-trusted-public-keys` options to `nh os switch`; afterward Nix uses the
|
||||
persistent settings.
|
||||
|
||||
## Decisions/provisioning still needed
|
||||
|
||||
@@ -87,8 +121,8 @@ Final full validation passed before the final review deletions:
|
||||
`/tmp/nixos-validate-t7zv1zux` (session 88912,
|
||||
completed exit 0). Formatting, devenv preparation, flake check, all three host
|
||||
builds (Orion, Polaris, Zenith), and the tools-only workbench build passed.
|
||||
This includes the final notes startup ordering, serialized vault-query patch,
|
||||
FUSE wrapper paths, native Zsh retry function and SecretSpec package collision fix.
|
||||
This includes the final notes startup ordering, FUSE wrapper paths, native Zsh retry
|
||||
function and SecretSpec package collision fix. The vault patch was removed afterward.
|
||||
No systems were activated.
|
||||
|
||||
Native devenv tools-only startup also passed in an isolated temporary home:
|
||||
@@ -101,9 +135,9 @@ Evidence: `/tmp/foundation-editor-check/{startup,notes}.log`. No real notebook o
|
||||
credentials loaded. Built Kanagawa index declares `Inherits=Adwaita,hicolor`.
|
||||
Python source syntax and local documentation links checked; no automated tests added.
|
||||
|
||||
The final review only removed the unaccepted Kubernetes login wrapper and the
|
||||
The earlier final review removed the unaccepted Kubernetes login wrapper and the
|
||||
machine-wide devenv cache setting; the flake-scoped cache remains. Full builds were
|
||||
not repeated for those deletions.
|
||||
not repeated for those deletions. The later Walker patch removal has not been built.
|
||||
|
||||
Builds do not establish interactive acceptance. The user checkpoint remains; do not
|
||||
repeat full builds for documentation-only handoff edits.
|
||||
@@ -112,18 +146,16 @@ repeat full builds for documentation-only handoff edits.
|
||||
|
||||
The final diff was reviewed for correctness, integration and Ponytail complexity.
|
||||
Desktop/capability moves and repository wiring had no material findings. The review
|
||||
removed the speculative Kubernetes login interpreter and kept the devenv cache at
|
||||
flake scope instead of granting it machine-wide trust. The remaining Python has a
|
||||
concrete role: in-memory concurrent secret loading with completeness checks, one-time
|
||||
encrypted credential reshaping, dynamic OBS rclone configuration, or pre-existing
|
||||
dictation/transcription behavior.
|
||||
removed the speculative Kubernetes login interpreter. The devenv cache was later
|
||||
moved from flake scope to machine-wide Nix settings at the user's request. The
|
||||
remaining Python has a concrete role: in-memory concurrent secret loading with
|
||||
completeness checks, one-time encrypted credential reshaping, dynamic OBS rclone
|
||||
configuration, or pre-existing dictation/transcription behavior.
|
||||
|
||||
The user checkpoint is still required before this pass is complete. No implementation
|
||||
commit was made in this turn.
|
||||
|
||||
Initial local commit `f164d8b` predates this implementation. Four documentation files
|
||||
were already modified during the design pass; those changes belong to this effort.
|
||||
No remote changes or activation have occurred. External workbench analysis/content
|
||||
The user checkpoint is still required before this pass is complete. The implementation
|
||||
was committed as `5748b34` after the initial foundation commit `f164d8b`. Later
|
||||
cleanup removed the Walker patch, Handy test and AI capability README.
|
||||
No activation was recorded during that pass. External workbench analysis/content
|
||||
changes are unrelated and must not be committed here. Previous external loader
|
||||
copies remain at `/tmp/workbench-environment-before-6k4dwzuo`; only root/workbench environment documentation and ignore entries were updated.
|
||||
Backups: `/tmp/foundation-workbench-docs-bvrs1hu9`. Old external loaders remain
|
||||
|
||||
+15
-10
@@ -22,6 +22,11 @@ a provisional ownership boundary, not a different workstation variant. Steam and
|
||||
LAN SSH on Polaris, and laptop power/firmware management on Zenith, are deliberate.
|
||||
Orion owns shared services. Tailnet administration supplements existing access;
|
||||
public Orion SSH closes only after private access is verified. Web services stay public.
|
||||
Orion installs Kitty terminfo for SSH sessions from the workstations.
|
||||
|
||||
Wardrowbe uses a password gateway for trusted household access, followed by profile
|
||||
selection inside the app; verified individual identity is deferred. Its internal AI
|
||||
is disabled. Paid API usage, a Codex bridge and local model integration are deferred.
|
||||
|
||||
Nix owns reproducible installation, integration and selected settings. Applications
|
||||
own credentials, sessions, content and deliberately interactive preferences. No
|
||||
@@ -52,8 +57,8 @@ Use store-qualified executables or `runtimeInputs` in packaged scripts; make run
|
||||
paths and failures explicit. Do not duplicate package lists, generated settings or
|
||||
binding references in documentation.
|
||||
|
||||
These clarify the agreed model; they are not a one-package-per-file rule, a new
|
||||
testing policy, or a requirement for additional abstractions.
|
||||
These clarify the agreed model; they are not a one-package-per-file rule or a
|
||||
requirement for additional abstractions.
|
||||
|
||||
## Daily environment
|
||||
|
||||
@@ -74,9 +79,9 @@ Notes stay in `~/sync/notes`, mostly meeting material; no new taxonomy. HTTP and
|
||||
database targets remain independently selected and visibly named. Dadbod working
|
||||
queries and connection state stay outside Git; see the editor's `database.lua`.
|
||||
|
||||
Kanagawa remains the theme with Adwaita fallback icons. rbw unlocks on requested
|
||||
vault access, preserving its lock policy. Outlook PWA owns work email/calendar
|
||||
editing. Mailspring owns personal mail; Thunderbird remains a backup. Noctalia
|
||||
Kanagawa remains the theme with Adwaita fallback icons. Walker uses upstream Elephant
|
||||
without a local vault patch; it may query rbw during startup. Outlook PWA owns work
|
||||
email/calendar editing. Mailspring owns personal mail; Thunderbird remains a backup. Noctalia
|
||||
provides the combined read-only Radicale/Outlook agenda. The user accepts published
|
||||
ICS link access and supplies the URL privately through runtime settings. Personal
|
||||
calendar editing stays on the phone; keep khal/todoman.
|
||||
@@ -118,11 +123,11 @@ validation feedback to repeated reminders. This applies the useful principle of
|
||||
progressive disclosure from [OpenAI's harness engineering article](https://openai.com/index/harness-engineering/)
|
||||
without introducing speculative skills, orchestration or evaluation infrastructure.
|
||||
|
||||
`just validate` includes working-tree changes and new nonignored files without staging,
|
||||
formats, evaluates and builds. Concise results and saved logs minimize agent overhead.
|
||||
Targeted host builds support iteration; a full run also builds workbench tools.
|
||||
Builds do not prove activation or interactive behavior. Preserve the user's testing
|
||||
policy; this pass does not create a new automated testing policy.
|
||||
`just validate` is available on explicit request. It includes working-tree changes
|
||||
and new nonignored files without staging, formats, evaluates and builds. Targeted
|
||||
host builds are supported; a full run also builds workbench tools. Builds do not
|
||||
prove activation or interactive behavior. Do not write or run tests or perform
|
||||
extensive validation unless explicitly requested.
|
||||
|
||||
Keep native update and activation commands. `nix flake update` is normal; selective
|
||||
updates (often `llm-agents`) are appropriate while nixpkgs breakage awaits repair.
|
||||
|
||||
Generated
+83
-71
@@ -20,16 +20,16 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788011267,
|
||||
"narHash": "sha256-mEq2kU+ljompTToZ44Afvm7d/rHJ5iMBl0tjZuyShJs=",
|
||||
"lastModified": 1790001035,
|
||||
"narHash": "sha256-1/SLBjSYBzDdDhvLQ83wrzBakyS/xNGgtxHGNuveOEQ=",
|
||||
"owner": "Mic92",
|
||||
"repo": "bun2nix",
|
||||
"rev": "5765b0614591f75ee8ba5596e81ae85c167d1071",
|
||||
"rev": "07a5bfc8ac36c5370199343fa620b69f63186e33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"ref": "fix-structured-attrs-hook",
|
||||
"ref": "llm-agents",
|
||||
"repo": "bun2nix",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -98,11 +98,11 @@
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1789773873,
|
||||
"narHash": "sha256-lFR8A3JzpXn4Az9quklprOje/+Njyh9+bP+CE1TCIxI=",
|
||||
"lastModified": 1791388908,
|
||||
"narHash": "sha256-eqnGuVYIh6u8XU6UXueceaCi3UfSqbvopeuLYgClEDY=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "2ba2f9ed32596289874c58981a4d3e56cadd639d",
|
||||
"rev": "27af3b2029a6d1274db8a570fb57292dae5a2551",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -118,11 +118,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781152676,
|
||||
"narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=",
|
||||
"lastModified": 1789770686,
|
||||
"narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1",
|
||||
"rev": "725ea35e410ad83be4931d1bff7e090eacaf3563",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -143,11 +143,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775706155,
|
||||
"narHash": "sha256-h7Rw0vlb0n0Jsk21WJPm7H+1T1bG+PEuxE5cJ2TZl8A=",
|
||||
"lastModified": 1790316550,
|
||||
"narHash": "sha256-Qr/8JQ8zpmmWmZ7UAjhxVdRbSgwQ0uc2r/wUBMe4NBk=",
|
||||
"owner": "abenz1267",
|
||||
"repo": "elephant",
|
||||
"rev": "376ee71c66db38683daabd57350bf3f6f086eaf8",
|
||||
"rev": "a0670fb2cf590a3ceed6f799a45947b86a78d5f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -198,11 +198,11 @@
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788450739,
|
||||
"narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=",
|
||||
"lastModified": 1790898470,
|
||||
"narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993",
|
||||
"rev": "024633cd702b10285db5cb19b40ad48d2399ba60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -219,11 +219,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788450739,
|
||||
"narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=",
|
||||
"lastModified": 1790898470,
|
||||
"narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993",
|
||||
"rev": "024633cd702b10285db5cb19b40ad48d2399ba60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -281,11 +281,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788651960,
|
||||
"narHash": "sha256-v9wJd32eZ2bvhBzVOd7TIjLQd011P7nwOhjKtWlci5I=",
|
||||
"lastModified": 1791306979,
|
||||
"narHash": "sha256-KuLePuhwJM9NLt/gTLHzXaOoSZKGoB3m7NfXjiQ98HY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "2c0350c759688177331b8f5242311fae8877bdb3",
|
||||
"rev": "fae6e9e42c3b762ab47635cddcfaf6f52374a61b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -318,11 +318,11 @@
|
||||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1789804571,
|
||||
"narHash": "sha256-qYKCHhnLrEQ5XOH/5vwc57FSpPNCWC/4+AcWjJa7vPE=",
|
||||
"lastModified": 1791440787,
|
||||
"narHash": "sha256-nRO1wEJmb4wjz+0Mhpg5VWURTqZRBZq3MvMjtPkKuAI=",
|
||||
"owner": "numtide",
|
||||
"repo": "llm-agents.nix",
|
||||
"rev": "c2351168cdce1d7ab47961266b999a449f23bfad",
|
||||
"rev": "2109db8971dc18137ff1ac9393627c761609600d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -357,11 +357,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788036898,
|
||||
"narHash": "sha256-3NT3yTvoRT7+rxLDNovpyeTDIJkZlBoO72rcu2x9Y9o=",
|
||||
"lastModified": 1790176416,
|
||||
"narHash": "sha256-acP7QvsB+dHghUeL9AwSSZ3qS//skpqjv484aveg1EQ=",
|
||||
"owner": "cachix",
|
||||
"repo": "nix",
|
||||
"rev": "b9b81726b38469c55b9706d80d37d6c73cc7f76c",
|
||||
"rev": "bd10d7f563420c6034b9d1dc75c4168fc01e5afc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -378,11 +378,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788680125,
|
||||
"narHash": "sha256-amGSoDobwmp4CFvCn841ws2iuitus+HUJdD/gKgsrJA=",
|
||||
"lastModified": 1791105314,
|
||||
"narHash": "sha256-oTM7QFgRQ+vxBpMBMc7hEYpqBtpXAzXu2xuB/tru84U=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "116ad1c2adb642405ef8916f6a94c8626f971344",
|
||||
"rev": "e740bc4e9d8918d7819a51486d5099930c65c72e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -398,11 +398,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788744583,
|
||||
"narHash": "sha256-oNMrijfyaoRjjWhxHNFSBYyEB4u/zb/AxoKewC56LvE=",
|
||||
"lastModified": 1791440872,
|
||||
"narHash": "sha256-PwiSn1VO3/6BD/Gxw/3Ei2sPB3SccyKyJ7nD72Y+WU4=",
|
||||
"owner": "BirdeeHub",
|
||||
"repo": "nix-wrapper-modules",
|
||||
"rev": "e88c449105c6aafa460196d3cbd16718655aee0f",
|
||||
"rev": "d82c328c504648fa952f25fac8332319eb425d4c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -444,11 +444,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788860136,
|
||||
"narHash": "sha256-MhPMOFV4pVkygWEbQ8t1De/uQ9cWF1u++tRe2L5tG48=",
|
||||
"lastModified": 1791373788,
|
||||
"narHash": "sha256-c3oMt0QoE+4yiRk6u1m2L9ogjaUw0uTGn9yk808KkgE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "62173785b9a18c78b4a15aca2623d02bceb9d077",
|
||||
"rev": "4bc63156b109ee7b4103e3ec30565c8c92bde435",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -463,11 +463,11 @@
|
||||
"nixpkgs-src": "nixpkgs-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1789506231,
|
||||
"narHash": "sha256-vNkJbtmqyBfFhn/HnzQo4ROuoyYWuy/allqTfJb4kMY=",
|
||||
"lastModified": 1787753358,
|
||||
"narHash": "sha256-Tl77VbWyAKrOfRNQhL6JbQtb/MLzbYa/1RG1gWWfICk=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "c2f38fe7f9e04d9aadd354d380f2bd40531d9737",
|
||||
"rev": "256551e45f6303e142ab4a98be1bf243feb77dc0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -479,11 +479,11 @@
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1788057806,
|
||||
"narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=",
|
||||
"lastModified": 1790477367,
|
||||
"narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c",
|
||||
"rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -495,11 +495,11 @@
|
||||
"nixpkgs-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1789370336,
|
||||
"narHash": "sha256-6RSEDHIWQtesQKWSu5qRai8L2h4KgCgMEfJHstW99G4=",
|
||||
"lastModified": 1787394516,
|
||||
"narHash": "sha256-pRGOQSClnXNI2iLUG6DYpsGvYcuw0drOutVZFTJNw90=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c7def046b9a883d46974757852106483d741586f",
|
||||
"rev": "c8f90650c15282fa8656a041bfbbd2403997a9a7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -511,11 +511,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1789632929,
|
||||
"narHash": "sha256-RjR8AyvGlWuw16XRj7C1YDEw4E27ciuyPeB2nDMzgTU=",
|
||||
"lastModified": 1790600678,
|
||||
"narHash": "sha256-6k3n7X2UsZ6tAlWTz99RimiZab+17tMUrw9sRUcELiA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a32edd7654519351e48e80372a928df336394670",
|
||||
"rev": "f45c6f04c2f013f004bf94e284e95d72898d9393",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -527,33 +527,45 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1788834054,
|
||||
"narHash": "sha256-kkWAS4mE+fmi+u3mxwD9/bfX6DGJ49Tv8O9kzN5r0HQ=",
|
||||
"rev": "e9b9cbecbf6c25ca26c150d78570e6332694a129",
|
||||
"lastModified": 1791336361,
|
||||
"narHash": "sha256-7WQwlykef1x8n7aoyw4XP6882i2NRs5F6dVCXZ1NI1g=",
|
||||
"rev": "7dd199b0e2993e37b4775ed66b1c291699608c9f",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1069601.e9b9cbecbf6c/nixexprs.tar.xz"
|
||||
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1086972.7dd199b0e299/nixexprs.tar.xz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1790822859,
|
||||
"narHash": "sha256-VBA0QerzzmL+4wxgtwiCdiLwLpJg2/9xOxhgO3BRJQA=",
|
||||
"rev": "c59305bab2065cfecc4944690d9eedbb56f3a9fa",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1083223.c59305bab206/nixexprs.tar.zst"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.zst"
|
||||
}
|
||||
},
|
||||
"noctalia": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788886125,
|
||||
"narHash": "sha256-5rgQFUGr8GXYyyuy8ynrN39WfZzSiO/wqGWjELBOkEY=",
|
||||
"lastModified": 1791427429,
|
||||
"narHash": "sha256-FzM3cunGIn8oDC1afUsXzGdfI/tK5HjPOHzHXFIAVx4=",
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia",
|
||||
"rev": "d6607b4eafbb92f6d494ebed3e296d4b741c0b58",
|
||||
"rev": "3e059de4aec58ba5b81f6c366b2b234a58f5ab0a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "noctalia-dev",
|
||||
"ref": "cachix",
|
||||
"repo": "noctalia",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -603,11 +615,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1788337237,
|
||||
"narHash": "sha256-gkSH8VUtCo6hnysNmb9DbTuDepH2t5pv+QWjP75xKAk=",
|
||||
"lastModified": 1791103873,
|
||||
"narHash": "sha256-nFxM+pKoZ8LJAEnUXARyCaOAloWgaW9kZQOSjWzKcTE=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "fbf759290e0cb0a98dfc813a4eb7d53ad1dacb57",
|
||||
"rev": "dcd241ba97088c22569d1573286e1b9daad340c0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -618,11 +630,11 @@
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"lastModified": 1791244623,
|
||||
"narHash": "sha256-uuanbkFk8a313Zfrxdcz8Us/yQtaxNnKJtX8v0ZPpd8=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"rev": "d36eeed142f88b5a636f2e3856a53c61654cf29b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -676,11 +688,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1786901030,
|
||||
"narHash": "sha256-WSFCsDSE5ffgD2MqzkM2CYjeFiKhRF/dJUN8uedb6YE=",
|
||||
"lastModified": 1791203292,
|
||||
"narHash": "sha256-vuzVwvjeucSnwKwMBpyP8r5IzdrMKCHEdwTrRFwUN7I=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "27b3b12a8e6375f28ebe122f07d230ca5459bbfa",
|
||||
"rev": "03d8ee1bcbc8f9638907bb79edb9673151d0e22b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -698,11 +710,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784217994,
|
||||
"narHash": "sha256-gxHJsrJZo2qbKK47Kf/9ho3i/HhRwkL8XvPnczGPd9E=",
|
||||
"lastModified": 1791441924,
|
||||
"narHash": "sha256-2SLAXtgtsZgjK+dyzDAV47oQNoip3dsGX+XXrT/udEk=",
|
||||
"owner": "abenz1267",
|
||||
"repo": "walker",
|
||||
"rev": "42b3ed88abf50bc52638fb2835b7f17e3ea3ac4c",
|
||||
"rev": "a515085fd39fae80acc086c8fbfd9b7771a9a11d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{
|
||||
description = "NixOS Configuration";
|
||||
|
||||
nixConfig = {
|
||||
extra-substituters = [ "https://devenv.cachix.org" ];
|
||||
extra-trusted-public-keys = [ "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" ];
|
||||
};
|
||||
|
||||
inputs = {
|
||||
devenv.url = "github:cachix/devenv";
|
||||
disko = {
|
||||
@@ -29,8 +24,8 @@
|
||||
};
|
||||
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
|
||||
noctalia = {
|
||||
url = "github:noctalia-dev/noctalia";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
url = "github:noctalia-dev/noctalia/cachix";
|
||||
# Keep upstream's nixpkgs pin to match its cached builds.
|
||||
};
|
||||
sops-nix = {
|
||||
url = "github:Mic92/sops-nix";
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# AI tools
|
||||
|
||||
Nix installs the tools, assets, skills and system Codex defaults. Codex owns its
|
||||
writable user configuration; credentials, session history and other runtime state
|
||||
remain outside this repository. `instructions/codex.md` owns global agent guidance.
|
||||
|
||||
Herdr is optional experimentation. Reload its managed configuration with
|
||||
Ctrl+Alt+Shift+R (or Ctrl+B then Shift+R); its configuration owns the binding reference.
|
||||
Home Manager may preserve an earlier regular configuration file with `.bak`.
|
||||
|
||||
Ollama supplies `nomic-embed-text` for grounded-docs. The latter runs on localhost
|
||||
port 6280 with persistent Podman volumes. Removing another tool must not delete
|
||||
these models or volumes. No mandatory agent persistence or orchestration workflow
|
||||
is defined here.
|
||||
@@ -28,6 +28,8 @@ in
|
||||
};
|
||||
|
||||
features.plugins = true;
|
||||
# The Nix package lacks the codex-package.json layout the daemon requires.
|
||||
features.daemon_auto_start = false;
|
||||
hooks = ai.codexHooks;
|
||||
mcp_servers = ai.servers // {
|
||||
context7 = ai.servers.context7 // {
|
||||
@@ -98,10 +100,11 @@ in
|
||||
pkgs.nodejs
|
||||
pkgs.python3
|
||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex
|
||||
pkgs.llm-agents.chatgpt
|
||||
pkgs.llm-agents.pi
|
||||
pkgs.llm-agents.claude-code
|
||||
pkgs.llm-agents.herdr
|
||||
pkgs.bubblewrap
|
||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
|
||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.pi
|
||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.claude-code
|
||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.herdr
|
||||
pkgs.ctx7
|
||||
];
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
|
||||
# Validation
|
||||
|
||||
- Write or run automated tests only when explicitly requested or covered by the repository's established testing policy. Do not invent a testing policy or introduce tests into a repository without tests unless explicitly requested.
|
||||
- Validate changes with the smallest relevant build, manual behaviour check, or review of code and output.
|
||||
- Broaden or repeat validation only for changes, failures or unresolved concerns. Report only checks performed.
|
||||
- Do not write or run tests or perform extensive validation unless explicitly requested.
|
||||
- For routine changes, use a focused review or small manual check. Report only checks performed.
|
||||
|
||||
# Writing
|
||||
|
||||
|
||||
@@ -8,4 +8,13 @@
|
||||
jack.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
flake.modules.homeManager.audio =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
home.packages = [
|
||||
pkgs.reaper
|
||||
pkgs.bitwig-studio
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -65,6 +65,7 @@
|
||||
dbeaver-bin
|
||||
onlyoffice-desktopeditors
|
||||
pinta
|
||||
audacity
|
||||
];
|
||||
xdg.mimeApps.defaultApplicationPackages = lib.mkAfter [ pkgs.onlyoffice-desktopeditors ];
|
||||
};
|
||||
|
||||
@@ -15,7 +15,6 @@ in
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = service.domain;
|
||||
ROOT_URL = "${service.origin}/";
|
||||
HTTP_PORT = 3001;
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
"""Synthetic key-state checks; never reads a keyboard or records audio."""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import push_to_talk as ptt
|
||||
|
||||
down = [ptt.key.KEY_LEFTMETA, ptt.key.KEY_D]
|
||||
|
||||
|
||||
def check(states, expected, error=None):
|
||||
device = Mock()
|
||||
device.active_keys.side_effect = states
|
||||
device.read_loop.return_value = iter([object(), object()])
|
||||
if error:
|
||||
device.read_loop.side_effect = error
|
||||
with (
|
||||
patch.object(ptt, "list_devices", return_value=["keyboard"]),
|
||||
patch.object(ptt, "InputDevice", return_value=device),
|
||||
patch.object(ptt.signal, "signal"),
|
||||
patch.object(ptt.subprocess, "run") as run,
|
||||
):
|
||||
try:
|
||||
ptt.main("handy")
|
||||
except (OSError, KeyboardInterrupt):
|
||||
assert error is not None
|
||||
assert [call.args[0][1] for call in run.call_args_list] == expected
|
||||
device.close.assert_called_once()
|
||||
|
||||
|
||||
check([[]], []) # Released before the listener starts: do not record.
|
||||
check([down, []], ["--toggle-transcription", "--toggle-transcription"])
|
||||
check([down, down, down, [ptt.key.KEY_D]], ["--toggle-transcription"] * 2)
|
||||
check([down, down], ["--toggle-transcription", "--cancel"], OSError("unplugged"))
|
||||
check([down, down], ["--toggle-transcription", "--cancel"], KeyboardInterrupt())
|
||||
assert ptt.held([ptt.key.KEY_RIGHTMETA, ptt.key.KEY_D])
|
||||
assert not ptt.held([ptt.key.KEY_LEFTMETA])
|
||||
print("Push-to-talk release, repeat, disconnect and cancellation checks passed")
|
||||
@@ -14,6 +14,14 @@ in
|
||||
settings = {
|
||||
trusted-users = [ "@wheel" ];
|
||||
use-xdg-base-directories = true;
|
||||
extra-substituters = [
|
||||
"https://devenv.cachix.org"
|
||||
"https://noctalia.cachix.org"
|
||||
];
|
||||
extra-trusted-public-keys = [
|
||||
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
|
||||
"noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="
|
||||
];
|
||||
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
|
||||
@@ -23,16 +23,6 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
elephantPackages = inputs.walker.inputs.elephant.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
# Upstream initializes rbw at startup. Drop this patch when it supports lazy vault access.
|
||||
providers = elephantPackages.elephant-providers.overrideAttrs (old: {
|
||||
patches = (old.patches or [ ]) ++ [ ./demand-driven-vault.patch ];
|
||||
});
|
||||
elephant = elephantPackages.elephant-with-providers.overrideAttrs (old: {
|
||||
installPhase =
|
||||
builtins.replaceStrings [ "${elephantPackages.elephant-providers}" ] [ "${providers}" ]
|
||||
old.installPhase;
|
||||
});
|
||||
walkerDefaults = builtins.fromTOML (builtins.readFile "${inputs.walker}/resources/config.toml");
|
||||
|
||||
launcher = pkgs.writeShellApplication {
|
||||
@@ -46,8 +36,6 @@
|
||||
{
|
||||
imports = [ inputs.walker.homeManagerModules.default ];
|
||||
|
||||
programs.elephant.package = elephant;
|
||||
|
||||
desktop.commands.launcher = [ (lib.getExe launcher) ];
|
||||
programs.walker = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
--- a/internal/providers/bitwarden/setup.go
|
||||
+++ b/internal/providers/bitwarden/setup.go
|
||||
@@ -34,7 +34,7 @@
|
||||
func Setup() {
|
||||
LoadConfig()
|
||||
|
||||
- initItems()
|
||||
+ // Vault access is initiated by an explicit query, never daemon startup.
|
||||
}
|
||||
|
||||
func LoadConfig() {
|
||||
--- a/internal/providers/bitwarden/query.go
|
||||
+++ b/internal/providers/bitwarden/query.go
|
||||
@@ -7,6 +7,7 @@
|
||||
"net"
|
||||
"os/exec"
|
||||
"strings"
|
||||
+ "sync"
|
||||
"time"
|
||||
|
||||
"github.com/abenz1267/elephant/v2/pkg/common"
|
||||
@@ -20,7 +21,24 @@
|
||||
Folder string `json:"folder"`
|
||||
}
|
||||
|
||||
+var itemsMu sync.Mutex
|
||||
+
|
||||
func initItems() {
|
||||
+ itemsMu.Lock()
|
||||
+ defer itemsMu.Unlock()
|
||||
+ initItemsLocked()
|
||||
+}
|
||||
+
|
||||
+func items() []RbwItem {
|
||||
+ itemsMu.Lock()
|
||||
+ defer itemsMu.Unlock()
|
||||
+ if cachedItems == nil {
|
||||
+ initItemsLocked()
|
||||
+ }
|
||||
+ return cachedItems
|
||||
+}
|
||||
+
|
||||
+func initItemsLocked() {
|
||||
cachedItems = nil
|
||||
cmd := exec.Command("rbw", "list", "--raw")
|
||||
output, err := cmd.CombinedOutput()
|
||||
@@ -40,7 +58,7 @@
|
||||
|
||||
entries := []*pb.QueryResponse_Item{}
|
||||
|
||||
- for k, v := range cachedItems {
|
||||
+ for k, v := range items() {
|
||||
var subtexts []string
|
||||
actions := []string{ActionCopyPassword, ActionCopyTotp, ActionSyncVault}
|
||||
if config.AutoTypeSupport {
|
||||
@@ -0,0 +1,131 @@
|
||||
# Wardrowbe on Orion
|
||||
|
||||
[Wardrowbe](https://github.com/Anyesh/wardrowbe) is served through the existing
|
||||
Caddy instance. The capability owns container images, routing, runtime secret
|
||||
templates and startup ordering. Image references and settings live in
|
||||
`default.nix`; endpoints live in the shared service facts.
|
||||
|
||||
Internal AI is disabled. Upload clothes and enter tags manually; automatic tagging
|
||||
and AI outfit generation are unavailable. Local rotation and background removal
|
||||
remain available. No AI provider key or notification provider is configured.
|
||||
|
||||
Tinyauth provides a cookie-based password gateway. After authenticating there,
|
||||
Wardrowbe's development login accepts an email/name to select a profile. Use a
|
||||
consistent email for each person. This is for a trusted household: gateway users
|
||||
can select one another's profiles. It is not verified individual identity.
|
||||
|
||||
## Provision before building or activating Orion
|
||||
|
||||
Add these top-level keys with `sops edit modules/secrets/secrets.yaml`, using the
|
||||
existing system-secret recipients. The keys are deliberately not provisioned by
|
||||
the configuration change; Orion's SOPS build checks require them to exist.
|
||||
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| `wardrowbe-postgres-password` | A new 64-character hexadecimal password |
|
||||
| `wardrowbe-secret-key` | A separate new 64-character hexadecimal signing secret |
|
||||
| `wardrowbe-nextauth-secret` | A separate new 64-character hexadecimal session secret |
|
||||
| `wardrowbe-auth-users` | A single-line `kiri:bcrypt-hash` string |
|
||||
|
||||
Generate each of the first three separately with `openssl rand -hex 32`. If
|
||||
OpenSSL is unavailable, use `nix run --quiet nixpkgs#openssl -- rand -hex 32`.
|
||||
Keep values inside the encrypted document; do not paste them into Nix or chat.
|
||||
Hexadecimal database passwords work directly in the application's connection URL.
|
||||
|
||||
On a workstation with Podman, create the gateway user interactively:
|
||||
|
||||
```console
|
||||
podman run --rm -it ghcr.io/tinyauthapp/tinyauth:v5.2.0@sha256:220aa235c76393a73fece831d7ba967b8698d3907fd8e3c4c952f699c7b142a5 user create --interactive
|
||||
```
|
||||
|
||||
Choose username `kiri` and your password, and answer **No** to Docker formatting.
|
||||
Put the emitted `username:hash` string
|
||||
in `wardrowbe-auth-users` as a quoted YAML scalar. Additional gateway accounts can
|
||||
be added as a comma-separated list on the same line. If Podman is unavailable,
|
||||
prefix its arguments with `nix run --quiet nixpkgs#podman --` instead of `podman`.
|
||||
This command only creates a hash; gateway sessions persist separately on Orion.
|
||||
|
||||
Create DNS records for `wardrobe.jelles.net` and `wardrobe-auth.jelles.net` pointing
|
||||
at Orion. Publish an AAAA record only if Orion has working public IPv6. Existing
|
||||
Caddy firewall access supplies HTTP/HTTPS and automatic certificates.
|
||||
|
||||
The private container network reserves `10.89.30.0/24`, with gateway
|
||||
`10.89.30.1`. It must not overlap Orion's routes. If changing it, update both the
|
||||
network declaration and Tinyauth's trusted-proxy address before first activation.
|
||||
|
||||
Add new source files to Git before using a Git-backed flake. From this repository,
|
||||
activate explicitly:
|
||||
|
||||
```console
|
||||
nixos-rebuild switch --quiet --target-host orion --sudo --flake .#orion
|
||||
```
|
||||
|
||||
The initial activation downloads container images, including the image-processing
|
||||
model. Allow time and disk space for those downloads. Containers start on boot;
|
||||
PostgreSQL and Redis become healthy before the backend runs `alembic upgrade head`.
|
||||
The frontend and workers wait for the backend's health check. A failed migration
|
||||
prevents the API from starting. Each container has a 15-minute startup deadline.
|
||||
|
||||
## Operation
|
||||
|
||||
Run these commands on Orion. Container names and unit names correspond directly
|
||||
to the declarations in `default.nix`:
|
||||
|
||||
```console
|
||||
sudo systemctl status podman-wardrowbe-backend.service
|
||||
sudo journalctl -u podman-wardrowbe-backend.service -n 80 --no-pager
|
||||
sudo podman ps --filter name=wardrowbe
|
||||
sudo podman volume ls --filter name=wardrowbe
|
||||
```
|
||||
|
||||
Persistent named volumes contain PostgreSQL, Redis's append-only queue, uploaded
|
||||
images and Tinyauth's SQLite sessions. They are root-owned Podman state under
|
||||
`/var/lib/containers/storage/volumes`, outside Nix. Container recreation and system
|
||||
rollback preserve these volumes; do not remove them or prune volumes. The network
|
||||
is also retained when services stop.
|
||||
|
||||
Only Caddy serves public traffic. Frontend, backend and gateway host ports bind to
|
||||
localhost; database and queue ports remain inside the container network. Every
|
||||
Wardrowbe route, including API and signed image URLs, passes through the gateway.
|
||||
The gateway's own login endpoint is public. Gateway cookies are secure, HTTP-only
|
||||
and scoped to `jelles.net` to support redirects between the two subdomains.
|
||||
|
||||
SOPS renders root-only mode-0400 environment files at activation. Changes to their
|
||||
contents restart the consuming containers. Rotating session secrets signs users out.
|
||||
Changing `POSTGRES_PASSWORD` alone does **not** change an existing database role's
|
||||
password: coordinate the database password change with the encrypted value.
|
||||
|
||||
## Upgrade and recovery
|
||||
|
||||
Review upstream release notes and migrations, then update the image tags and
|
||||
manifest digests together. Upgrade backend and frontend to the same release;
|
||||
workers use the backend image. Image updates happen through explicit configuration
|
||||
activation, with no automatic image updater. Review resource requirements before
|
||||
enabling AI later.
|
||||
|
||||
If startup fails, inspect the failing container unit's journal. After correcting
|
||||
the cause, start the affected units and any dependents whose startup was blocked.
|
||||
To restart the complete application in dependency order:
|
||||
|
||||
```console
|
||||
sudo systemctl restart podman-wardrowbe-postgres.service podman-wardrowbe-redis.service podman-wardrowbe-backend.service podman-wardrowbe-worker.service podman-wardrowbe-image-worker.service podman-wardrowbe-frontend.service podman-wardrowbe-auth.service
|
||||
```
|
||||
|
||||
Reverting a NixOS generation restores configuration and image references, not
|
||||
database schema changes. Do not assume an older application can use a migrated
|
||||
database; follow upstream recovery guidance. No backup system is added here.
|
||||
|
||||
## Manual acceptance after activation
|
||||
|
||||
- Open the wardrobe in a private browser window. It should require the gateway
|
||||
password; unauthenticated API and image requests should also be blocked.
|
||||
- Authenticate, select a Wardrowbe profile, complete onboarding and upload a photo.
|
||||
Add tags manually and confirm the photo renders; try a rotation.
|
||||
- With the gateway session active, open `/api/v1/capabilities` on the wardrobe
|
||||
origin. Both internal AI capabilities should be `false`.
|
||||
- Restart the application and confirm the profile, photo and tags remain present.
|
||||
- Check that both public hostnames have valid HTTPS certificates and that the
|
||||
existing Orion web services still work.
|
||||
|
||||
No tests, builds, activation or browser acceptance checks were performed while
|
||||
preparing this capability.
|
||||
@@ -0,0 +1,234 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
nixosModules = config.flake.modules.nixos;
|
||||
in
|
||||
{
|
||||
flake.modules.nixos.wardrowbe =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
service = config.facts.services.wardrowbe;
|
||||
auth = config.facts.services.wardrowbe-auth;
|
||||
podman = lib.getExe config.virtualisation.podman.package;
|
||||
# Multi-architecture manifest digests; updating a tag alone cannot change an image.
|
||||
images = {
|
||||
backend = "ghcr.io/anyesh/wardrowbe:backend-1.10.3@sha256:75fd6f85fb7b91ccbb227b52d616bab11b5130c4e22858579f45736419fb592d";
|
||||
frontend = "ghcr.io/anyesh/wardrowbe:frontend-1.10.3@sha256:730cf52bd8a03b94473b129e9a988b3dae9818e9377fd88917029156ee7a2e17";
|
||||
auth = "ghcr.io/tinyauthapp/tinyauth:v5.2.0@sha256:220aa235c76393a73fece831d7ba967b8698d3907fd8e3c4c952f699c7b142a5";
|
||||
postgres = "docker.io/library/postgres:15-alpine@sha256:f7d23353e1b15400d22ebe31189f4d314b87a4c129cc400c8c2d8d4ca127bf81";
|
||||
redis = "docker.io/library/redis:7-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499";
|
||||
};
|
||||
healthOptions = [
|
||||
"--health-interval=10s"
|
||||
"--health-timeout=5s"
|
||||
"--health-start-period=30s"
|
||||
"--health-retries=6"
|
||||
"--health-on-failure=kill"
|
||||
];
|
||||
backendContainer = {
|
||||
image = images.backend;
|
||||
environment = {
|
||||
# Profile selection is available only behind the password gateway.
|
||||
DEBUG = "true";
|
||||
AI_INTERNAL_ENABLED = "false";
|
||||
AI_VISION_ENABLED = "false";
|
||||
AI_TEXT_ENABLED = "false";
|
||||
APP_URL = service.origin;
|
||||
CORS_ORIGINS = builtins.toJSON [ service.origin ];
|
||||
REDIS_URL = "redis://wardrowbe-redis:6379/0";
|
||||
STORAGE_PATH = "/data/uploads";
|
||||
LOG_LEVEL = "INFO";
|
||||
};
|
||||
environmentFiles = [ config.sops.templates."wardrowbe-backend.env".path ];
|
||||
volumes = [ "wardrowbe-uploads:/data/uploads" ];
|
||||
};
|
||||
backendUnits = [
|
||||
"podman-wardrowbe-backend.service"
|
||||
"podman-wardrowbe-worker.service"
|
||||
"podman-wardrowbe-image-worker.service"
|
||||
];
|
||||
containers = {
|
||||
wardrowbe-postgres = {
|
||||
image = images.postgres;
|
||||
environment = {
|
||||
POSTGRES_USER = "wardrobe";
|
||||
POSTGRES_DB = "wardrobe";
|
||||
};
|
||||
environmentFiles = [ config.sops.templates."wardrowbe-postgres.env".path ];
|
||||
volumes = [ "wardrowbe-postgres:/var/lib/postgresql/data" ];
|
||||
podman.sdnotify = "healthy";
|
||||
extraOptions = healthOptions ++ [
|
||||
"--health-cmd=pg_isready -h 127.0.0.1 -U wardrobe -d wardrobe"
|
||||
];
|
||||
};
|
||||
wardrowbe-redis = {
|
||||
image = images.redis;
|
||||
cmd = [
|
||||
"redis-server"
|
||||
"--appendonly"
|
||||
"yes"
|
||||
];
|
||||
volumes = [ "wardrowbe-redis:/data" ];
|
||||
podman.sdnotify = "healthy";
|
||||
extraOptions = healthOptions ++ [ "--health-cmd=redis-cli ping" ];
|
||||
};
|
||||
wardrowbe-backend = backendContainer // {
|
||||
dependsOn = [
|
||||
"wardrowbe-postgres"
|
||||
"wardrowbe-redis"
|
||||
];
|
||||
ports = [ "127.0.0.1:8002:8000" ];
|
||||
cmd = [
|
||||
"sh"
|
||||
"-c"
|
||||
"alembic upgrade head && exec uvicorn app.main:app --host 0.0.0.0 --port 8000"
|
||||
];
|
||||
podman.sdnotify = "healthy";
|
||||
extraOptions = healthOptions ++ [
|
||||
"--health-cmd=curl --fail --silent http://127.0.0.1:8000/api/v1/health"
|
||||
];
|
||||
};
|
||||
wardrowbe-worker = backendContainer // {
|
||||
dependsOn = [ "wardrowbe-backend" ];
|
||||
cmd = [
|
||||
"arq"
|
||||
"app.workers.worker.WorkerSettings"
|
||||
];
|
||||
};
|
||||
wardrowbe-image-worker = backendContainer // {
|
||||
dependsOn = [ "wardrowbe-backend" ];
|
||||
cmd = [
|
||||
"arq"
|
||||
"app.workers.image_worker.ImageWorkerSettings"
|
||||
];
|
||||
};
|
||||
wardrowbe-frontend = {
|
||||
image = images.frontend;
|
||||
dependsOn = [ "wardrowbe-backend" ];
|
||||
environment = {
|
||||
BACKEND_URL = "http://wardrowbe-backend:8000";
|
||||
NEXTAUTH_URL = service.origin;
|
||||
DEV_MODE = "true";
|
||||
};
|
||||
environmentFiles = [ config.sops.templates."wardrowbe-frontend.env".path ];
|
||||
ports = [ "127.0.0.1:3002:3000" ];
|
||||
podman.sdnotify = "healthy";
|
||||
extraOptions = healthOptions ++ [
|
||||
"--health-cmd=node -e \"fetch('http://127.0.0.1:3000').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))\""
|
||||
];
|
||||
};
|
||||
wardrowbe-auth = {
|
||||
image = images.auth;
|
||||
environment = {
|
||||
TINYAUTH_APPURL = auth.origin;
|
||||
TINYAUTH_AUTH_SECURECOOKIE = "true";
|
||||
TINYAUTH_AUTH_TRUSTEDPROXIES = "10.89.30.1";
|
||||
TINYAUTH_LABELPROVIDER = "none";
|
||||
TINYAUTH_ANALYTICS_ENABLED = "false";
|
||||
TINYAUTH_DATABASE_PATH = "/data/tinyauth.db";
|
||||
TINYAUTH_UI_TITLE = "Wardrobe login";
|
||||
};
|
||||
environmentFiles = [ config.sops.templates."wardrowbe-auth.env".path ];
|
||||
volumes = [ "wardrowbe-auth:/data" ];
|
||||
ports = [ "127.0.0.1:3003:3000" ];
|
||||
podman.sdnotify = "healthy";
|
||||
extraOptions = healthOptions ++ [ "--health-cmd=tinyauth healthcheck" ];
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
nixosModules.caddy
|
||||
nixosModules.sops
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
wardrowbe-postgres-password = { };
|
||||
wardrowbe-secret-key = { };
|
||||
wardrowbe-nextauth-secret = { };
|
||||
wardrowbe-auth-users = { };
|
||||
};
|
||||
sops.templates = {
|
||||
"wardrowbe-postgres.env" = {
|
||||
content = ''
|
||||
POSTGRES_PASSWORD=${config.sops.placeholder.wardrowbe-postgres-password}
|
||||
'';
|
||||
restartUnits = [ "podman-wardrowbe-postgres.service" ];
|
||||
};
|
||||
"wardrowbe-backend.env" = {
|
||||
content = ''
|
||||
DATABASE_URL=postgresql+asyncpg://wardrobe:${config.sops.placeholder.wardrowbe-postgres-password}@wardrowbe-postgres:5432/wardrobe
|
||||
SECRET_KEY=${config.sops.placeholder.wardrowbe-secret-key}
|
||||
'';
|
||||
restartUnits = backendUnits;
|
||||
};
|
||||
"wardrowbe-frontend.env" = {
|
||||
content = ''
|
||||
NEXTAUTH_SECRET=${config.sops.placeholder.wardrowbe-nextauth-secret}
|
||||
'';
|
||||
restartUnits = [ "podman-wardrowbe-frontend.service" ];
|
||||
};
|
||||
"wardrowbe-auth.env" = {
|
||||
content = ''
|
||||
TINYAUTH_AUTH_USERS=${config.sops.placeholder.wardrowbe-auth-users}
|
||||
'';
|
||||
restartUnits = [ "podman-wardrowbe-auth.service" ];
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.oci-containers = {
|
||||
backend = "podman";
|
||||
containers = lib.mapAttrs (
|
||||
_: container:
|
||||
{
|
||||
networks = [ "wardrowbe" ];
|
||||
}
|
||||
// container
|
||||
) containers;
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
wardrowbe-network = {
|
||||
description = "Wardrowbe container network";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
${podman} network exists wardrowbe || \
|
||||
${podman} network create --subnet 10.89.30.0/24 --gateway 10.89.30.1 wardrowbe
|
||||
'';
|
||||
};
|
||||
}
|
||||
// lib.mapAttrs' (
|
||||
name: _:
|
||||
lib.nameValuePair "podman-${name}" {
|
||||
requires = [ "wardrowbe-network.service" ];
|
||||
after = [ "wardrowbe-network.service" ];
|
||||
serviceConfig.TimeoutStartSec = lib.mkForce 900;
|
||||
}
|
||||
) containers;
|
||||
|
||||
services.caddy.virtualHosts = {
|
||||
${auth.domain}.extraConfig = "reverse_proxy 127.0.0.1:3003";
|
||||
${service.domain}.extraConfig = ''
|
||||
request_body {
|
||||
max_size 50MB
|
||||
}
|
||||
route {
|
||||
forward_auth 127.0.0.1:3003 {
|
||||
uri /api/auth/caddy
|
||||
}
|
||||
handle /api/auth/* {
|
||||
reverse_proxy 127.0.0.1:3002
|
||||
}
|
||||
handle /api/* {
|
||||
reverse_proxy 127.0.0.1:8002
|
||||
}
|
||||
handle {
|
||||
reverse_proxy 127.0.0.1:3002
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
kubelogin-oidc
|
||||
jq
|
||||
just
|
||||
python3Packages.python-openstackclient
|
||||
python314
|
||||
rclone
|
||||
sops
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
in
|
||||
{
|
||||
# devenv already installs its bundled SecretSpec CLI in the workstation profile.
|
||||
home.packages =
|
||||
lib.remove pkgs.secretspec (import ./_support/tools.nix { inherit pkgs; }).packages;
|
||||
home.packages = lib.remove pkgs.secretspec (import ./_support/tools.nix { inherit pkgs; }).packages;
|
||||
programs.zsh.initContent = lib.mkAfter ''
|
||||
workbench-reload() {
|
||||
if [[ "''${DEVENV_ROOT:-}" != ${lib.escapeShellArg root} ]]; then
|
||||
|
||||
@@ -235,6 +235,14 @@ in
|
||||
scheme = "https";
|
||||
domain = "vault.jelles.net";
|
||||
};
|
||||
wardrowbe = {
|
||||
scheme = "https";
|
||||
domain = "wardrobe.jelles.net";
|
||||
};
|
||||
wardrowbe-auth = {
|
||||
scheme = "https";
|
||||
domain = "wardrobe-auth.jelles.net";
|
||||
};
|
||||
};
|
||||
|
||||
externalDevices.pixel-10.syncthingId = "MTJHEHA-UMZDQZ7-BTMRRLQ-Y7BFPUJ-ZTY6LZX-PDXV3IS-XVJCU7B-EPETBQZ";
|
||||
|
||||
@@ -10,7 +10,7 @@ in
|
||||
stateVersion = "24.05";
|
||||
};
|
||||
|
||||
flake.modules.nixos.orion = {
|
||||
flake.modules.nixos.orion = { pkgs, ... }: {
|
||||
imports = [
|
||||
nixosModules.host-base
|
||||
|
||||
@@ -24,11 +24,13 @@ in
|
||||
nixosModules.actual
|
||||
nixosModules.gitea
|
||||
nixosModules.transcription
|
||||
nixosModules.wardrowbe
|
||||
./_hardware.nix
|
||||
./_disk.nix
|
||||
];
|
||||
|
||||
environment.enableAllTerminfo = true;
|
||||
# SSH clients on both workstations use Kitty.
|
||||
environment.systemPackages = [ pkgs.kitty.terminfo ];
|
||||
|
||||
users.users.${config.facts.account.name}.linger = true;
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ in
|
||||
flake.modules.homeManager.workstation-base = {
|
||||
imports = [
|
||||
homeModules.passwords
|
||||
homeModules.audio
|
||||
homeModules.clipboard
|
||||
homeModules.handy
|
||||
homeModules.desktop-commands
|
||||
|
||||
@@ -5,6 +5,10 @@ orion-ip: ENC[AES256_GCM,data:S6fpCWnD8dvchvrHlEo=,iv:72+oRxHUEJ7imJ+sWjGbG+TUrS
|
||||
hashed-password: ENC[AES256_GCM,data:mhYvALF/VrPMFFYEIGiML1MoRxdOI/J9akZPD+OF5drDTR4J5LBn3EejlbzP8CTCRsyoIF6tigMBxF8ZLz9W7hOVwT70Hr/yXfLWJ2lfBsf7l/SPZ+6NglKppCeQQktm4QKIHTVj7CkbRw==,iv:0RxXkb+vz/QK9dvecCZpWCWCsoPhi2F3OCt6CwUDqX4=,tag:j7QO8xUfWUnSpk4mMQUYmA==,type:str]
|
||||
gemini-api-key-neovim: ENC[AES256_GCM,data:B8FeFt45FsU3aagyLDKXiwmx0mRrsw4C8RQ3EWXwZ+YfWLMvwJad,iv:1HqBD6vc07Ke/PMYXfHqFrWDGw/UMjiiBjLRN33/xHI=,tag:czcrYGbJFi41rYtIPM4qTQ==,type:str]
|
||||
booklore-db-pass: ENC[AES256_GCM,data:dlPGXQ24itEaBRJSJ9WOogWCdF3atFQ2ZtlLGyGq8Tin5OmSZI6lZUzSE+femBW5SBTIlKQvzHEPCs9MT5tyMIqetzGLm+mMN3FDW7si684Cuv9z9Uq5gjAZWh14KQMWYPI=,iv:oLnqu2EDFBVcBpswVRXXeF617YolPxOUx9CscHRRn/8=,tag:Si6gF1EXhcHalk11D3Exlw==,type:str]
|
||||
wardrowbe-auth-users: ENC[AES256_GCM,data:0padDqNkWA9p6GXaX3bpyH78tEeOndlX6/Gm0OzsfecnPkJmBJUQZr/328+51Q4eWPRflg4NRm04nejrqohKGcs=,iv:VJQD/ko4B18PbJh0gWdfQJ3xlGeHW4oBlho4e3Bkhk8=,tag:iE7gfUi1khmwIJA/3L8zvA==,type:str]
|
||||
wardrowbe-postgres-password: ENC[AES256_GCM,data:3t+py1nmtzbdFFMbBtQXQKttRj1MQrz+wcfjQGPYahOaQTIDu1Pzk3KJf+LANCTftpvrwO6N92K0b5q0+1MEzw==,iv:o9Hiew2vx6OinLBOKgPyx0K+WVTAvPopcEJoLtYCZTY=,tag:xi0wueITInYXwvVaLusqyw==,type:str]
|
||||
wardrowbe-secret-key: ENC[AES256_GCM,data:c9++BrtGsAFHML3gUG/E319jg9kxixH8RfZqs9pymxjYEFJsclaiWmknqeel4luIAuD5ufvDRzBLqxaBSE6rhQ==,iv:YntoeASLdE+lbU+15eIaR4SqWU3PzaWH8MJFlW1FwaM=,tag:aZhDTPc3qbNTZ8N9lvCJgA==,type:str]
|
||||
wardrowbe-nextauth-secret: ENC[AES256_GCM,data:3UZm0L+0q7C6OVYfCyIghzK80dPKOOz9BLfFCHctD2oMckPl0yfL5S1NqsXULycx+ctwWPV7SQj7/AiD6cyw1w==,iv:SocQDS2GbQ6ZWifmwb7AJC7SNkAMjJWetlTM9TfUC3Q=,tag:WuXajPY4e4zF5T6zC7okTQ==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
@@ -25,7 +29,7 @@ sops:
|
||||
sWu/+CcQDpUu4tAeBSCUZ/BV2nTvfb94DZGK2dWUFniJaZit5tRZlg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1upsxyevxdv3xax8jhnffclryuve70k63cjrca69ffds4h2m3nvuql59ufw
|
||||
lastmodified: "2026-08-08T14:56:00Z"
|
||||
mac: ENC[AES256_GCM,data:pXcvH73xNMSkOGytdhJ4Qu1pH8d3qS/FkPfGvbkzQoNLKRlLiArJExPYIkEtFdr7mDhYer91wPtkJu2HyyxCVPkPp8EFaeVdGuFufLQruQjP2KRfR841hohVW4KN53nh1AJT22CW2LTqgS0BnTBrd6wUQWvBHdek99eh8vwgurI=,iv:d8I+vKIgfirDvkHXVSNWJrKUO5vACkbk3VSN8TXSE+Q=,tag:itzAvtD+aBFmDilxZBepLw==,type:str]
|
||||
lastmodified: "2026-10-10T13:58:26Z"
|
||||
mac: ENC[AES256_GCM,data:S21qc5jLIoRrR28yiNmQHAU9soV74haGAbYXxsut0PqeRAMzUj4RSdBiR7Mja84r+w148Gx4GqTrPLhVxfj+78lyWcV3MWYbf9rr4tbxUYbhlJPRwVPdeP/JEc4rhPzX7QnUcrlym2zOhumJ/RoUHWW2yUEC/7DmzCqMXH1Kx5U=,iv:p7lwWl76cvELLhMlOdnxFdYdoIt/tVwxL/ihR/T3d7Y=,tag:DWsJYfaIZ2yZqXPktl9V1g==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.2
|
||||
version: 3.13.3
|
||||
Reference in new issue
Block a user