Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 6 additions & 4 deletions .github/docs-sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ stack-manager's user documentation is published at [uniskela.com/docs/stack-mana
by `uniskela/.com`, the same way as adhd-hub and ts6-manager.

- [`docs/manifest.json`](../docs/manifest.json) lists the pages to publish: `source` file, URL `slug`, sidebar `title`
and `group`. Design docs, ADRs and plans that are not listed stay on GitHub only; links to them fall back to GitHub
URLs on the site.
and `group`. Published pages live under `docs/public/`. `docs/internal/` (plans, architecture decisions) and
`docs/agents/` are not imported; links to them fall back to GitHub URLs on the site.
- The `Notify Uniskela documentation` workflow sends an update notification after README/docs changes merge to
`main` (and on each published release). It does not publish the website directly: `uniskela/.com` imports the
content, runs its checks and proposes a draft PR for review.
Expand All @@ -27,5 +27,7 @@ Never put the App private key in repository files, PRs or chats.

## Adding a page

Write it in `docs/`, link it from [`docs/index.md`](../docs/index.md) and add an entry to `docs/manifest.json`. Use
relative links between docs so they work both on GitHub and on the site.
Write it in `docs/public/`, link it from [`docs/public/index.md`](../docs/public/index.md) and add an entry to
`docs/manifest.json`. The slug is the public URL and does not include `public`. Use relative links between docs so
they work both on GitHub and on the site. Put implementation plans and architecture decisions in `docs/internal/`,
and agent-only notes in `docs/agents/`.
22 changes: 12 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Guidance for coding agents working on **stack-manager**.

## Product boundary

Read [docs/PRODUCT.md](docs/PRODUCT.md) and [docs/adr/0005-product-boundary.md](docs/adr/0005-product-boundary.md) before adding features.
Read [docs/public/PRODUCT.md](docs/public/PRODUCT.md) and [docs/internal/adr/0005-product-boundary.md](docs/internal/adr/0005-product-boundary.md) before adding features.

This app manages Git-backed **source/configuration** for Compose stacks. It is **not** a Portainer/Komodo/Arcane replacement. No Containers/Images/Networks/Volumes management pages. Runtime is optional and read-only.

Expand All @@ -15,14 +15,14 @@ forge webhook receiver, relevance rules, selective deploy). PR #2 (application f
and PR #4 (Git workflow: commit, safe push, conflict protection, stack history, Changes UI; released in v0.5.0) are
done. Do not build secrets providers, runtime watch or PWA work ahead of their phases.

See [docs/plans/MVP_PLAN.md](docs/plans/MVP_PLAN.md) and the code layout in
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#code-layout-implemented-in-pr-2-extended-through-v050).
See [docs/public/plans/MVP_PLAN.md](docs/public/plans/MVP_PLAN.md) and the code layout in
[docs/public/ARCHITECTURE.md](docs/public/ARCHITECTURE.md#code-layout-implemented-in-pr-2-extended-through-v050).

## Working in the code

- `pnpm check` must pass (format, lint, typecheck, tests). `pnpm build` must succeed.
- PR titles (and so squash-merge commits) must be Conventional Commits (`feat:`, `fix:`, `docs:`, …); Release
Please derives versions and the changelog from them. See [docs/RELEASING.md](docs/RELEASING.md).
Please derives versions and the changelog from them. See [docs/public/RELEASING.md](docs/public/RELEASING.md).
- Schema changes: edit `src/server/persistence/schema.ts`, run `pnpm db:generate`, commit the migration.
- API routes: always wrap handlers with `defineRoute` (auth is default-deny; a coverage test enforces this).
- Services receive dependencies through `src/server/container.ts`; depend on ports, not Drizzle.
Expand All @@ -32,9 +32,11 @@ See [docs/plans/MVP_PLAN.md](docs/plans/MVP_PLAN.md) and the code layout in
- Read repository content through `SourceTreeReader` (Git objects, never the working tree). Never return the
contents of secret-looking files (`isSecretPath` in `src/shared/source/paths.ts`) or accept drafts for them.
- `src/shared` is pure code shared by server and browser (no Node, React or server imports; lint-enforced).
- User docs are published to uniskela.com from `docs/manifest.json` (see `.github/docs-sync.md`). When a feature
changes what users see, update `docs/getting-started.md`/`docs/installation.md`; list new user-facing pages in the
manifest.
- User docs are published to uniskela.com from `docs/manifest.json` (see `.github/docs-sync.md`). Write them under
`docs/public/` (setup, deployment, backups, security and other user-facing references). Implementation plans and
architecture decisions go under `docs/internal/`. Agent-only notes go under `docs/agents/`; this file stays the
canonical agent guide. When a feature changes what users see, update `docs/public/getting-started.md` /
`docs/public/installation.md` and list new pages in the manifest. Do not change published slugs.
- UI tests: `pnpm build && pnpm test:e2e` (set `E2E_GIT_REMOTE`/`E2E_STACK_ROOT` to a public repo and stack folder to include the editor tests).

## Tech direction (locked)
Expand All @@ -47,12 +49,12 @@ See [docs/plans/MVP_PLAN.md](docs/plans/MVP_PLAN.md) and the code layout in

## Prior art

`uniskela/stackwise` is an unrelated inventory SPA. Do not import its code. See [docs/PRIOR_ART.md](docs/PRIOR_ART.md).
`uniskela/stackwise` is an unrelated inventory SPA. Do not import its code. See [docs/internal/PRIOR_ART.md](docs/internal/PRIOR_ART.md).

## Security

Never log or commit credentials. Encrypt provider secrets at rest. Redact audit events. See [docs/SECURITY.md](docs/SECURITY.md).
Never log or commit credentials. Encrypt provider secrets at rest. Redact audit events. See [docs/public/SECURITY.md](docs/public/SECURITY.md).

## Docs map

[docs/INDEX.md](docs/INDEX.md)
[docs/internal/INDEX.md](docs/internal/INDEX.md)
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,29 @@ drafts and Compose validation, stack docs and an environment inventory.
**New in v0.5.0, the Git workflow:** review drafts on the Changes tab, commit them with your own Git identity
(validation errors block, warnings need acknowledgement), and push safely to the tracked branch. Stack Manager never
force pushes, stops when the remote branch has changed, and keeps your drafts whatever happens. Each stack has a
History tab with the commits and diffs that touched it. See [Git workflow](docs/GIT_WORKFLOW.md).
History tab with the commits and diffs that touched it. See [Git workflow](docs/public/GIT_WORKFLOW.md).

**Next:** deployment routing, which deploys only the stacks a commit changed through Portainer or a generic
webhook. See the [roadmap](docs/plans/MVP_PLAN.md).
webhook. See the [roadmap](docs/public/plans/MVP_PLAN.md).

**Documentation:** [uniskela.com/docs/stack-manager](https://uniskela.com/docs/stack-manager/) (source in
[docs/](docs/index.md)).
[docs/](docs/public/index.md)).

| Document | Purpose |
| --- | --- |
| [Installation](docs/installation.md) | Run the published container image with Docker Compose |
| [Getting started](docs/getting-started.md) | First run, connecting a repository, stacks and the editor |
| [Git workflow](docs/GIT_WORKFLOW.md) | Commit, push, remote changes and stack history |
| [Self-hosting reference](docs/SELF_HOSTING.md) | Configuration, data directory, reverse proxy, upgrades |
| [Product](docs/PRODUCT.md) / [Architecture](docs/ARCHITECTURE.md) | What it is (and is not), and how it is built |
| [Docs index](docs/INDEX.md) | Every design, planning and operations document |
| [Installation](docs/public/installation.md) | Run the published container image with Docker Compose |
| [Getting started](docs/public/getting-started.md) | First run, connecting a repository, stacks and the editor |
| [Git workflow](docs/public/GIT_WORKFLOW.md) | Commit, push, remote changes and stack history |
| [Self-hosting reference](docs/public/SELF_HOSTING.md) | Configuration, data directory, reverse proxy, upgrades |
| [Product](docs/public/PRODUCT.md) / [Architecture](docs/public/ARCHITECTURE.md) | What it is (and is not), and how it is built |
| [Docs index](docs/internal/INDEX.md) | Every design, planning and operations document |


## Using this project with AI coding agents

If you use Codex, Cursor, Claude Code, or another assistant with [Context7 MCP](https://context7.com/), you can ask it to consult Stack Manager's documentation before making changes. Context7 is optional and is separate from the application's Git and deployment integrations.

> Use Context7 MCP to resolve the official documentation library for `uniskela/stack-manager` (expected ID: `/uniskela/stack-manager`), then retrieve guidance for installation, repository connections, the editor and Git workflow, environment inventory, self-hosting, and troubleshooting. Match the guidance to the Stack Manager version I'm running. If Context7 is unavailable, the lookup returns an error, the library is still indexing, or the library doesn't cover that version, consult the [maintained documentation](https://uniskela.com/docs/stack-manager/) and [source Markdown](docs/index.md) instead.
> Use Context7 MCP to resolve the official documentation library for `uniskela/stack-manager` (expected ID: `/uniskela/stack-manager`), then retrieve guidance for installation, repository connections, the editor and Git workflow, environment inventory, self-hosting, and troubleshooting. Match the guidance to the Stack Manager version I'm running. If Context7 is unavailable, the lookup returns an error, the library is still indexing, or the library doesn't cover that version, consult the [maintained documentation](https://uniskela.com/docs/stack-manager/) and [source Markdown](docs/public/index.md) instead.

## Quick start (Docker Compose)

Expand All @@ -63,7 +63,7 @@ Put stack-manager behind a TLS-terminating reverse proxy and set `STACK_MANAGER_
For plain-HTTP testing on localhost set `STACK_MANAGER_COOKIE_SECURE=false`.

The container runs as a non-root user with a read-only root filesystem; all state lives in the `/data`
volume. No Docker socket is mounted. See [docs/installation.md](docs/installation.md).
volume. No Docker socket is mounted. See [docs/public/installation.md](docs/public/installation.md).

## Development

Expand Down
7 changes: 7 additions & 0 deletions docs/agents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Agent notes

Canonical instructions for this repository are [AGENTS.md](../../AGENTS.md). Do not copy them here.

Product boundary: [PRODUCT.md](../public/PRODUCT.md) and [ADR 0005](../internal/adr/0005-product-boundary.md).

Maintainer index: [INDEX.md](../internal/INDEX.md).
File renamed without changes.
File renamed without changes.
43 changes: 25 additions & 18 deletions docs/INDEX.md → docs/internal/INDEX.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
# Documentation index

Architecture, planning and operations docs for **stack-manager**. User documentation starts at [index.md](index.md)
and is published at [uniskela.com/docs/stack-manager](https://uniskela.com/docs/stack-manager/); the pages it publishes
are listed in [manifest.json](manifest.json) (see [../.github/docs-sync.md](../.github/docs-sync.md)).
Architecture, planning and operations docs for **stack-manager**. User documentation lives in
[public/](../public/index.md) and is published at
[uniskela.com/docs/stack-manager](https://uniskela.com/docs/stack-manager/); the pages it publishes
are listed in [manifest.json](../manifest.json) (see [docs-sync](../../.github/docs-sync.md)).

| Tree | What belongs there |
| --- | --- |
| [public/](../public/index.md) | Setup, deployment, backups, security and other user-facing references |
| internal/ (this file) | Implementation plans, architecture decisions and maintainer references |
| [agents/](../agents/README.md) | Agent notes. Canonical instructions stay in [AGENTS.md](../../AGENTS.md) |

## User guide

| Doc | Summary |
| --- | --- |
| [index.md](index.md) | Overview: what stack-manager does and does not do |
| [installation.md](installation.md) | Docker Compose install, image tags, upgrades |
| [getting-started.md](getting-started.md) | First run, repositories, stacks, editor, drafts, commit and push |
| [GIT_WORKFLOW.md](GIT_WORKFLOW.md) | Commit, safe push, remote changes, stack history; API reference |
| [index.md](../public/index.md) | Overview: what stack-manager does and does not do |
| [installation.md](../public/installation.md) | Docker Compose install, image tags, upgrades |
| [getting-started.md](../public/getting-started.md) | First run, repositories, stacks, editor, drafts, commit and push |
| [GIT_WORKFLOW.md](../public/GIT_WORKFLOW.md) | Commit, safe push, remote changes, stack history; API reference |

## Product and architecture

| Doc | Summary |
| --- | --- |
| [PRODUCT.md](PRODUCT.md) | Definition, hierarchy, non-goals, success criteria |
| [ARCHITECTURE.md](ARCHITECTURE.md) | Modular monolith, providers, request flows |
| [PRODUCT.md](../public/PRODUCT.md) | Definition, hierarchy, non-goals, success criteria |
| [ARCHITECTURE.md](../public/ARCHITECTURE.md) | Modular monolith, providers, request flows |
| [PRIOR_ART.md](PRIOR_ART.md) | Portainer, Komodo, Arcane, Dockge, stackwise, etc. |
| [plans/MVP_PLAN.md](plans/MVP_PLAN.md) | PR #2–#8 implementation sequence |
| [plans/MVP_PLAN.md](../public/plans/MVP_PLAN.md) | Published roadmap: PR #2–#8 sequence |
| [plans/UI_UX_PLAN.md](plans/UI_UX_PLAN.md) | UI/UX review of PR #2 and phased improvement plan |
| [plans/2026-09-30-dashboard-stacks-settings-design.md](plans/2026-09-30-dashboard-stacks-settings-design.md) | Dashboard home, organised stacks, settings split (slice A) |
| [plans/2026-09-30-dashboard-stacks-settings-implementation.md](plans/2026-09-30-dashboard-stacks-settings-implementation.md) | Implementation plan for slice A (nav, dashboard, stacks, settings, account) |
Expand All @@ -35,22 +42,22 @@ are listed in [manifest.json](manifest.json) (see [../.github/docs-sync.md](../.
| [providers/DEPLOYMENT_PROVIDER.md](providers/DEPLOYMENT_PROVIDER.md) | Deploy-only providers |
| [providers/RUNTIME_PROVIDER.md](providers/RUNTIME_PROVIDER.md) | Optional read-only runtime |
| [providers/SECRET_PROVIDER.md](providers/SECRET_PROVIDER.md) | Secret metadata / references |
| [STACK_DISCOVERY.md](STACK_DISCOVERY.md) | Repository → stack scopes |
| [STACK_DISCOVERY.md](../public/STACK_DISCOVERY.md) | Repository → stack scopes |
| [DEPLOYMENT_ROUTING.md](DEPLOYMENT_ROUTING.md) | Path relevance and push router |
| [GIT_WORKFLOW.md](GIT_WORKFLOW.md) | Edit → validate → commit → push → history (implemented in v0.5.0) |
| [GIT_WORKFLOW.md](../public/GIT_WORKFLOW.md) | Edit → validate → commit → push → history (implemented in v0.5.0) |
| [DEPLOYMENT_WATCH.md](DEPLOYMENT_WATCH.md) | CI-like deploy feedback |

## Operations and UX

| Doc | Summary |
| --- | --- |
| [SELF_HOSTING.md](SELF_HOSTING.md) | Configuration, data directory, Docker, upgrades |
| [RELEASING.md](RELEASING.md) | CI workflows, Conventional Commits, Release Please, GHCR images |
| [AUTH_AND_CREDENTIALS.md](AUTH_AND_CREDENTIALS.md) | Auth, encryption at rest |
| [SECURITY.md](SECURITY.md) | Threat model and controls |
| [SELF_HOSTING.md](../public/SELF_HOSTING.md) | Configuration, data directory, Docker, upgrades |
| [RELEASING.md](../public/RELEASING.md) | CI workflows, Conventional Commits, Release Please, GHCR images |
| [AUTH_AND_CREDENTIALS.md](../public/AUTH_AND_CREDENTIALS.md) | Auth, encryption at rest |
| [SECURITY.md](../public/SECURITY.md) | Threat model and controls |
| [UX.md](UX.md) | Desktop / mobile / PWA |
| [BACKUP_RESTORE.md](BACKUP_RESTORE.md) | Backup and restore |
| [TESTING.md](TESTING.md) | Testing strategy |
| [BACKUP_RESTORE.md](../public/BACKUP_RESTORE.md) | Backup and restore |
| [TESTING.md](../public/TESTING.md) | Testing strategy |

## Architecture decision records

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,9 @@ Never return hashes/tokens. Session `id` in API responses is the **hashed** sess
### Task 8: Docs + e2e polish + final verification

**Files:**
- `docs/getting-started.md` / `docs/UX.md` — mention Dashboard home and settings tabs if user-facing
- `docs/INDEX.md` — link this plan if not already
- `docs/plans/2026-09-30-dashboard-stacks-settings-design.md` — status → implemented (when done)
- `docs/public/getting-started.md` / `docs/internal/UX.md` — mention Dashboard home and settings tabs if user-facing
- `docs/internal/INDEX.md` — link this plan if not already
- `docs/internal/plans/2026-09-30-dashboard-stacks-settings-design.md` — status → implemented (when done)
- `tests/e2e/shell.spec.ts` — full nav order assertion

- [ ] **Step 1: Update docs for IA change**
Expand Down Expand Up @@ -560,7 +560,7 @@ await expect(nav.getByRole('link', { name: 'Settings' })).toBeVisible();

## Execution handoff

Plan saved to `docs/plans/2026-09-30-dashboard-stacks-settings-implementation.md`.
Plan saved to `docs/internal/plans/2026-09-30-dashboard-stacks-settings-implementation.md`.

**Two execution options:**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The Stacks page should be **clean**, **predictable to scan** (ordering you can r

## Method and limits

Read `src/app/w/[workspaceId]/stacks/page.tsx`, `src/ui/stacks/organised-stacks.tsx`, `src/shared/stacks/group-stacks.ts`, the `.list`/`.list-row`/`.pill`/`.search-field` CSS, the stack layout/tabs, `StackService`, `docs/UX.md` and the earlier UI plans.
Read `src/app/w/[workspaceId]/stacks/page.tsx`, `src/ui/stacks/organised-stacks.tsx`, `src/shared/stacks/group-stacks.ts`, the `.list`/`.list-row`/`.pill`/`.search-field` CSS, the stack layout/tabs, `StackService`, `docs/internal/UX.md` and the earlier UI plans.

The first pass was read-only, so visual findings were inferred from markup and CSS. Step 0 then ran a production build with a seeded dataset and checked them against screenshots (results below).

Expand Down Expand Up @@ -231,18 +231,18 @@ monorepo paths, 8 drafts, one repository in `error` with no fetch), captured wit
### Phase S5 — Finish (docs/test)

- Axe on `/stacks` at 390 px and 1280 px, light/dark, with filters open and with a chip row; check focus order and the live region.
- Update `docs/UX.md` ("Stacks — organised inventory (groups, search, filters, sort)"), `docs/getting-started.md` (how to find a stack), and mark this plan's status. List nothing new in `docs/manifest.json` unless a new user-facing page appears.
- Add this plan to `docs/INDEX.md` (note: that file currently has uncommitted changes in the working tree, so reconcile before editing).
- Update `docs/internal/UX.md` ("Stacks — organised inventory (groups, search, filters, sort)"), `docs/public/getting-started.md` (how to find a stack), and mark this plan's status. List nothing new in `docs/manifest.json` unless a new user-facing page appears.
- Add this plan to `docs/internal/INDEX.md` (note: that file currently has uncommitted changes in the working tree, so reconcile before editing).
- `pnpm check` and `pnpm build` green; `pnpm test:e2e` with `E2E_GIT_REMOTE`/`E2E_STACK_ROOT` for the editor-dependent tests.

**Done.**

- Axe runs in e2e on `/stacks` in its default, no-match, collapsed-folder and filters-open states (the mobile
disclosure included), at desktop and Pixel 7 sizes, light and dark. There is no chip row (see S3). The switcher
header was checked separately (S4).
- `docs/getting-started.md` gains a "Find a stack" section; `docs/UX.md` describes the new page and links here. No new
- `docs/public/getting-started.md` gains a "Find a stack" section; `docs/internal/UX.md` describes the new page and links here. No new
user-facing page, so `docs/manifest.json` is unchanged.
- Not done: the `docs/INDEX.md` entry. That file has an unrelated uncommitted rewrite in the owner's working tree;
- Not done: the `docs/internal/INDEX.md` entry. That file has an unrelated uncommitted rewrite in the owner's working tree;
add this plan when that lands.

## Outcome against the success criteria
Expand Down
Loading
Loading