94 lines
5.3 KiB
Markdown
94 lines
5.3 KiB
Markdown
# Milestone 6 - Gitea repository intelligence
|
|
|
|
Milestone 6 was completed on 2026-07-27 through commit `0af5254`. The
|
|
authoritative runtime was the restricted Unraid validation stack at
|
|
a private validation host, using Node.js 24.18.0 and PostgreSQL 17.9.
|
|
|
|
## Delivered boundary
|
|
|
|
- Gitea connection creation, safe detail, connection test, token rotation and
|
|
deletion are workspace-authorized and same-origin protected.
|
|
- Tokens are stored only as versioned AES-256-GCM envelopes. API and UI
|
|
projections return the last four characters, never plaintext, ciphertext,
|
|
nonce or authentication tag.
|
|
- Outbound requests enforce normalized URLs, DNS/IP policy, an explicit host
|
|
allowlist, redirect revalidation, authentication-header stripping on host
|
|
changes, timeouts and response-size limits.
|
|
- Capability probing records supported, unsupported, forbidden and temporarily
|
|
unavailable states without making optional evidence a global failure.
|
|
- Repository discovery is cursor-paginated. Import queues only IDs and a
|
|
bounded read-only collection mode; the worker reloads secrets and targets
|
|
inside the authorized server boundary.
|
|
- Deterministic detectors inspect only allowlisted manifests and documentation.
|
|
Repository commands remain inert prompt context and are never executed.
|
|
- A completed snapshot stores capability evidence, bounded file digests,
|
|
collection time, findings and a SHA-256 evidence digest. Initial profile
|
|
creation is transactional and immutable.
|
|
- Imported repository status is read from PostgreSQL and remains visible when
|
|
discovery is unavailable. Deleting a connection nulls its integration links
|
|
while preserving the local repository, complete snapshot and profile.
|
|
|
|
## Minimum Gitea permissions
|
|
|
|
Create a dedicated ordinary Gitea user or token with read access only to the
|
|
repositories that DevRunbook may inspect. The token needs repository listing,
|
|
repository metadata and file-content read access. Branch, tag, release,
|
|
language, topic, workflow, template, branch-protection and effective-permission
|
|
read access are optional: DevRunbook records those capabilities individually
|
|
when the server or token does not provide them.
|
|
|
|
Do not grant administrator access, repository write, issue write, pull-request
|
|
write, release write, webhook write or settings write. DevRunbook's first
|
|
adapter exposes no methods for creating or changing branches, commits, issues,
|
|
pull requests, releases, webhooks or repository settings.
|
|
|
|
For private HTTP Gitea, an operator must both opt into private-network HTTP and
|
|
put the exact host in `GITEA_ALLOWED_HOSTS`. The production validation allowlist
|
|
was restored to its fixed operator host after the isolated fixture was removed.
|
|
|
|
## Verification evidence
|
|
|
|
The following evidence was produced against commit `0af5254`:
|
|
|
|
- Clean Node 24 container: formatting, lint and typecheck passed for all 14
|
|
workspaces; all unit tests passed; all 14 production builds passed; 11
|
|
security tests passed.
|
|
- Focused PostgreSQL integration: the Gitea persistence suite passed against
|
|
the live PostgreSQL 17.9 service, including workspace isolation, encrypted
|
|
envelopes, latest status, retained-complete state and immutable revisions.
|
|
- Clean Python 3.12 container: 28 P0 packages, six normative examples, 72
|
|
catalog entries, nine schemas and all 28 golden prompts passed.
|
|
- Live Gitea 1.27.0 fixture: connection creation returned safe identity and
|
|
version; discovery returned exactly one repository; import returned `202`;
|
|
the worker completed the job; the snapshot had a 64-character digest,
|
|
findings and one immutable profile revision.
|
|
- Collected evidence did not include executable command output or execute
|
|
commands found in the fixture. The adapter invoked only read endpoints.
|
|
- With the Gitea fixture stopped, the integration page showed discovery as
|
|
unavailable while displaying the completed imported repository and retained
|
|
snapshot. The repository detail and profile APIs both returned `200`.
|
|
- At 390 by 844, the integration page had no horizontal overflow
|
|
(`innerWidth=390`, document and body scroll widths `375`).
|
|
- After deleting the temporary integration, PostgreSQL retained exactly one
|
|
local repository, one complete snapshot and one profile revision; both local
|
|
repository APIs still returned `200`.
|
|
- Production web, worker and PostgreSQL were healthy after cleanup. Web and
|
|
worker ran as `node`, with read-only roots and all Linux capabilities dropped.
|
|
- A scan of current web/worker logs found none of the configured validation
|
|
secret values, authorization headers or bearer credentials.
|
|
|
|
The isolated Gitea container, volume, temporary credentials, cookie jars and
|
|
response files were removed after the drill. The validation owner password was
|
|
restored and sessions were revoked. The restricted pre-M6 logical backup is
|
|
`/mnt/user/appdata/devrunbook-validation/backups/pre-m6-a4ab0c8.dump`; encryption
|
|
keys remain separate from ordinary backup evidence.
|
|
|
|
## Deliberate boundary for Milestone 7
|
|
|
|
The application use case can queue a new read-only snapshot with a caller-owned
|
|
idempotency key. A user-facing refresh review must present a diff and must not
|
|
silently overwrite an existing manual or immutable profile revision. That
|
|
review and acceptance workflow belongs with Prompt Lab authoring and review in
|
|
Milestone 7; the initial import path already creates and retains its immutable
|
|
profile as required by Milestone 6.
|