repo: add LICENSE, THIRD_PARTY.md, .dockerignore, hadolint lint, IDEAS backlog
Lint / hadolint (push) Successful in 9s
Lint / actionlint (push) Successful in 16s

Repo/CI hygiene batch (none base-affecting; image contents unchanged):

- LICENSE: actual MIT file (repo previously declared MIT only in prose).
- THIRD_PARTY.md: notes bundled software + licenses (pi/pi-fork/pi-obsmem/
  pi-studio MIT, gosu Apache-2.0, Debian packages under their own terms).
- .dockerignore: trims build context to what the Dockerfiles COPY (rootfs/ +
  entrypoint*.sh); keeps .git/docs/scripts/compose out. Verified it excludes
  none of the required COPY sources.
- lint.yml: new hadolint job (pinned v2.14.0) lints both Dockerfiles;
  .hadolint.yaml grandfathers deliberate choices (DL3008/DL3016/DL4006/DL3003/
  SC2086, mirroring the shellcheck excludes), fails on anything new at warning+.
  Verified hadolint exit 0 and the repo shell-guard passes with the new job.
- IDEAS.md: parks deferred follow-ups (SHA-pin actions, trivy, buildx SBOM/
  provenance, Makefile, renovate).
- README/DOCKER_HUB License sections now link LICENSE + THIRD_PARTY.md.

No tag.
This commit is contained in:
pi
2026-07-13 18:20:44 +02:00
parent 38d8832d34
commit 291ae5345e
9 changed files with 243 additions and 3 deletions
+35
View File
@@ -0,0 +1,35 @@
# Keep the Docker build context minimal and prevent stray files (notably
# `.git`) from ever being pulled in by a future broad COPY. Both Dockerfiles
# only COPY `rootfs/` and `entrypoint*.sh`, so everything below is safe to
# exclude from the context.
#
# DO NOT add `rootfs/`, `entrypoint.sh`, `entrypoint-user.sh`, or the
# Dockerfiles here — they are required to build the image.
# VCS / CI metadata
.git
.gitea
.gitignore
.dockerignore
# Lint / editor config
.hadolint.yaml
.editorconfig
# Docs & project meta
README.md
DOCKER_HUB.md
CHANGELOG.md
AGENTS.md
IDEAS.md
LICENSE
THIRD_PARTY.md
docs
# Local orchestration & examples (compose runs the image; not a build input)
docker-compose.yml
docker-compose.mempalace.yml
.env.example
# Repo tooling / tests (run from a checkout, not baked into the image)
scripts
+25 -1
View File
@@ -1,4 +1,4 @@
name: Lint workflows name: Lint
# Durable guard against CI-workflow bugs — most importantly the recurring # Durable guard against CI-workflow bugs — most importantly the recurring
# "bash-only syntax under the default `sh`/dash shell" footgun that broke # "bash-only syntax under the default `sh`/dash shell" footgun that broke
@@ -67,3 +67,27 @@ jobs:
# ("no project was found"). Globbing the workflow files is the # ("no project was found"). Globbing the workflow files is the
# supported way to lint a non-GitHub layout. # supported way to lint a non-GitHub layout.
run: actionlint -color .gitea/workflows/*.yml run: actionlint -color .gitea/workflows/*.yml
hadolint:
# Lint the two Dockerfiles that ARE the project (the shell/actions linting
# above never looked at them). Config — ignored rules + failure threshold
# — lives in .hadolint.yaml, which hadolint reads automatically, so a local
# `hadolint Dockerfile.base` reproduces CI exactly.
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- uses: actions/checkout@v4
- name: Install hadolint (pinned)
env:
HADOLINT_VERSION: 2.14.0
run: |
curl -fsSL \
"https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-x86_64" \
-o /usr/local/bin/hadolint
chmod +x /usr/local/bin/hadolint
hadolint --version
- name: Run hadolint
run: hadolint Dockerfile.base Dockerfile.variant
+27
View File
@@ -0,0 +1,27 @@
# hadolint configuration for pi-devbox.
#
# Both Dockerfiles are linted in CI (.gitea/workflows/lint.yml → `hadolint`
# job). hadolint reads this file automatically, so a local
# `hadolint Dockerfile.base` reproduces CI exactly.
#
# The ignores below are DELIBERATE project choices — they mirror the
# philosophy of the shellcheck excludes already applied to `run:` steps
# (SHELLCHECK_OPTS in lint.yml). Anything NOT listed here still fails the
# build at `warning` and above, so new Dockerfile smells are caught going
# forward.
ignored:
- DL3008 # "pin apt versions" — intentionally unpinned: the base tracks
# Debian stable and runs `apt-get upgrade`, so pinning point
# versions would rot and fight security updates.
- DL3016 # "pin npm versions" — pi's version IS pinned, but via the
# PI_VERSION build-arg (CI-resolved from npm), not the npm CLI.
- DL4006 # "set -o pipefail before a pipe" — the piped RUNs are
# download|extract steps with their own retries / `set -e`.
# Switching the global SHELL to bash is a larger, base-affecting
# change — tracked in IDEAS.md.
- DL3003 # "use WORKDIR, not cd" — cosmetic in the few `cd` RUNs here.
- SC2086 # "double-quote to prevent word-splitting" — the same code is
# excluded for shell `run:` steps in lint.yml; splitting is
# intentional in these contexts.
failure-threshold: warning
+23
View File
@@ -33,6 +33,29 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`).
overridden per-user (`:set notermguicolors`, or your own init). Base-affecting overridden per-user (`:set notermguicolors`, or your own init). Base-affecting
(`Dockerfile.base` apt package + COPY), rebuilds `base-<hash>`. (`Dockerfile.base` apt package + COPY), rebuilds `base-<hash>`.
- **Repository hygiene: `LICENSE`, `THIRD_PARTY.md`, and `.dockerignore`.** The
repo declared MIT only in prose; it now ships an actual `LICENSE` file (MIT,
© Joakim Persson) plus `THIRD_PARTY.md` recording that the published images
bundle third-party software under its own terms (pi, pi-fork,
pi-observational-memory, pi-studio — all MIT; gosu Apache-2.0; Debian packages
under their respective licenses). A new `.dockerignore` trims the build
context to what the Dockerfiles actually `COPY` (`rootfs/` + `entrypoint*.sh`),
keeping `.git`, docs, `scripts/`, and compose files out — cheaper context and
no risk of a future broad `COPY` pulling in `.git`. Not base-affecting (the
base hash covers only `Dockerfile.base` + `rootfs/` + `entrypoint*.sh`);
image contents are byte-identical.
- **Dockerfile linting (`hadolint`) in CI, plus an `IDEAS.md` backlog.** The
lint workflow already ran actionlint + shellcheck on `run:` steps but never
looked at the two Dockerfiles that are the heart of the project. A new
`hadolint` job (pinned v2.14.0, same download-pin pattern as actionlint) lints
`Dockerfile.base` and `Dockerfile.variant`; `.hadolint.yaml` grandfathers the
deliberate choices (unpinned apt/npm, `cd`-in-`RUN`, `SC2086` — mirroring the
existing shellcheck excludes) and fails on anything new at `warning`+.
`IDEAS.md` parks the vetted-but-unscheduled follow-ups (SHA-pin CI actions,
trivy scanning, buildx SBOM/provenance attestations, a local `Makefile`,
renovate). Repo/CI only — not baked into the image.
### Changed ### Changed
- **`-studio` images now pin pi-studio to its newest *semver tag* instead of - **`-studio` images now pin pi-studio to its newest *semver tag* instead of
+2 -1
View File
@@ -156,4 +156,5 @@ Optional volumes for MemPalace (commented out by default — uncomment in `docke
## License ## License
MIT (the image; pi and the bundled tools each carry their own licenses). MIT (the image; pi and the bundled tools each carry their own licenses). See
`LICENSE` and `THIRD_PARTY.md` in the [source repo](https://gitea.jordbo.se/joakimp/pi-devbox).
+60
View File
@@ -0,0 +1,60 @@
# Ideas & backlog
A living list of potential improvements for pi-devbox that are **not yet
scheduled**. This is intentionally lightweight — a place to park ideas so they
aren't lost between sessions. When an item ships, describe it in
[`CHANGELOG.md`](CHANGELOG.md) and remove it from here.
Rough effort tags: 🟢 small · 🟡 medium · 🔴 large. Status: `idea` (unvetted) ·
`planned` (agreed, not started).
---
## Supply-chain hardening
- 🟡 `planned`**Pin CI actions to commit SHAs.** The workflows use floating
major tags (`actions/checkout@v4`, `docker/build-push-action@v7`,
`docker/setup-buildx-action@v4`, `docker/login-action@v3`,
`docker/setup-qemu-action@v3`). This is inconsistent with the project's own
philosophy of SHA-pinning *content* refs (pi, pi-studio, pi-fork, …) to defeat
floating refs. Pin each action to a SHA with a trailing `# vX.Y.Z` comment.
Pairs naturally with the renovate item below to keep the pins fresh.
- 🟡 `planned`**Vulnerability scanning in CI.** No CVE scan runs on the
published images today. Add a `trivy image` (or grype) job to
`docker-publish.yml` after `smoke`. Start non-blocking (report only), then
tighten to fail on `HIGH`/`CRITICAL` with an available fix.
- 🟢🟡 `planned` — **Standardize build provenance → buildx SBOM + attestations.**
The image already carries hand-rolled provenance (OCI labels +
`build-manifest`). `docker/build-push-action` can emit a standard SBOM and
SLSA provenance attestation nearly for free (`provenance: mode=max`,
`sbom: true`). Makes provenance machine-consumable and pairs well with the
trivy item (scan the SBOM).
## Dockerfile hardening
- 🟡 `idea`**Address hadolint DL4006 properly.** Currently ignored in
`.hadolint.yaml`. The clean fix is `SHELL ["/bin/bash", "-o", "pipefail",
"-c"]` so piped `RUN`s fail on the first non-zero stage. This changes the
default `RUN` shell from `sh` to `bash` for all subsequent layers, so it is
base-affecting and needs a careful pass over existing `RUN`s before removing
the ignore.
## Developer experience
- 🟢 `idea`**`Makefile`/`justfile` for local iteration.** Reproducing a CI
build locally means hand-assembling many `--build-arg`s. Thin targets
(`make build-base`, `make build-variant`, `make smoke`, `make lint`) would
make local testing painless and document the canonical invocations.
- 🟡 `idea`**Dependency-update automation (renovate).** With CI actions
SHA-pinned (above), a `renovate.json` keeps those pins — plus the pinned tool
versions (`ACTIONLINT_VERSION`, `HADOLINT_VERSION`, gosu, etc.) — current via
automated PRs. Requires a renovate runner against the Gitea instance.
## Housekeeping
- 🟢 `idea`**Registry retention for `base-<hash>` tags.** The base-hash
caching scheme accumulates `base-<hash>` tags over time. Confirm whether the
registry prunes old ones, and add a retention/cleanup step if not.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Joakim Persson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+4 -1
View File
@@ -783,4 +783,7 @@ The pi coding-agent itself is [@earendil-works/pi-coding-agent](https://www.npmj
## License ## License
MIT MIT — see [`LICENSE`](LICENSE). This covers the repository's own contents
(Dockerfiles, entrypoint scripts, `rootfs/` seeds, CI, docs). The published
images bundle third-party software under their own licenses; see
[`THIRD_PARTY.md`](THIRD_PARTY.md).
+46
View File
@@ -0,0 +1,46 @@
# Third-party notices
pi-devbox is distributed under the MIT License (see [`LICENSE`](LICENSE)), which
covers **this repository's own contents** — the Dockerfiles, entrypoint scripts,
`rootfs/` seeds, CI workflows, and docs.
The **published container images** (`joakimp/pi-devbox:*`) additionally *bundle*
third-party software, each of which remains under its own license. This file is
a good-faith summary; the authoritative sources are the upstream projects and,
for OS packages, the per-package copyright files inside the image at
`/usr/share/doc/<package>/copyright`.
## pi and its extensions (installed in the variant layer)
| Component | Upstream | License |
| --- | --- | --- |
| pi (`@earendil-works/pi-coding-agent`) | npm | MIT |
| pi-fork | github.com/elpapi42/pi-fork | MIT |
| pi-observational-memory | github.com/elpapi42/pi-observational-memory | MIT |
| pi-studio *(`-studio` variant only)* | github.com/omaclaren/pi-studio | MIT |
| pi-toolkit, pi-extensions, mempalace-toolkit | authored by the maintainer (Joakim Persson) | MIT |
## Tooling baked into the base image
| Component | Upstream | License (best effort) |
| --- | --- | --- |
| gosu | github.com/tianon/gosu | Apache-2.0 |
| Node.js | nodejs.org | MIT (bundles components under their own licenses) |
| uv | github.com/astral-sh/uv | Apache-2.0 OR MIT |
| Neovim | neovim.io | Apache-2.0 + Vim license |
| Pandoc | pandoc.org | GPL-2.0-or-later |
| Typst | github.com/typst/typst | Apache-2.0 |
| ripgrep / fd / micro / tealdeer / yq (mikefarah) | respective repos | MIT / Apache-2.0 / Unlicense (varies) |
## Base OS
The image is built `FROM` a Debian base and installs packages via `apt`. Debian
and its packages are distributed under their respective licenses (GPL, LGPL,
MIT, BSD, and others). See each package's copyright file in the image under
`/usr/share/doc/<package>/copyright`.
---
*Licenses marked "best effort" are widely known but were not each verified at
the exact bundled version; consult the upstream project for authoritative
terms. Corrections welcome.*