This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user