GOTTAGIT_IMPLEMENTATION_PLAN.md
103 KB • MD • aug. 23, 2026 17:16
# GottaGit Implementation Plan
Status: confirmed design, ready for AI-led implementation
Workspace: `C:\Projects\GitServer`
Solution: `GitServer.slnx`
Product name: GottaGit
Target: .NET 10, self-contained `win-x64`, ASP.NET Core on IIS
This document is the controlling implementation plan. An AI coordinator must not start a wave until every prerequisite gate is complete. A feature is not complete because its types, markup, or tests exist; it is complete only when the real backend, authorization, persistence, failure behavior, user interface, and end-to-end evidence all pass together.
User-directed gate amendments: on 2026-08-22, all required Files-derived themes and assets were authorized for implementation, and legal review was deferred to user-owned release preparation without further implementation-time provenance investigation. Existing provenance records remain historical engineering inputs rather than implementation blockers. On 2026-08-23, unavailable W0 reference-host measurements/final approval and W1 target-host validation were changed from implementation-progression blockers to deferred release gates so implementation could proceed without an available Windows Server reference host. That amendment accepts the existing W0 inventory, scope, version, provenance, proposed numeric boundaries, and retained workstation/Windows-client IIS proofs for implementation progression only. It does not pass the W0 host gate or convert those inputs into Windows Server, OpenSSH, lifecycle, load, resource, or release evidence; the explicit deferrals in `docs/architecture/w1-deferred-validation.md` remain mandatory at their reassigned W3, I5, W10, W11, or release gates.
## 1. Mission
Build a production-capable, self-hosted Git forge for minor teams by selectively porting the best UI, theme, Monaco, preview, and Playwright concepts from Files and combining them with a modern native-Git server architecture inspired by Bonobo.Git.Server.
GottaGit must provide real Git hosting rather than a visual simulation. Every visible count, state, chart, file, commit, check, permission, and action must come from Git, SQLite, or another documented authoritative store. There must be no `coming soon` pages, fake repositories, unconditional success responses, dead controls, demo metrics, or hardcoded production data.
## 2. Success Envelope
Release 1 is designed and tested for this explicit small-team envelope:
| Dimension | Release gate |
|---|---:|
| Repositories | 100 |
| Users | 25 |
| Concurrent Git RPCs across HTTP and SSH | 5 |
| Largest tested repository | 2 GB |
| Largest tested tree | 10,000 entries |
| Metadata page latency | p95 below 1 second on the documented reference host |
| Browser gate | Chromium desktop and mobile |
| Visual gate | Core pages in every ported application theme |
W0 must freeze one reproducible reference-host manifest before implementation baselines are approved. The default target is exactly 4 vCPU, 16 GiB RAM, one 200 GiB fixed-size NTFS data volume on SSD-class storage, one fixed supported Windows Server build, one IIS/OpenSSH configuration, and a recorded CPU/hypervisor/disk benchmark. `docs/performance/reference-host.json` records image/build, patches, CPU model or VM SKU, memory, storage model/size/IOPS/latency, antivirus policy, network path, IIS settings, dataset seed/hash, load-tool versions, and numeric resource caps. Required caps include Web/Worker/native-Git RSS, handles, child processes, queued RPCs/jobs, WAL bytes/checkpoint age, log bytes, spool count/bytes, temp count/bytes, cleanup deadline, reservation heartbeat, and recovery deadline. An independent performance reviewer approves those values in W0; later widening is a design change, not a way to make a failing test pass. Results from a faster or differently configured machine do not replace this profile.
The 2 GB repository means a bare repository whose directory is 2 GiB after the documented full maintenance/GC command. The 10,000-entry case means one Git tree with 10,000 direct entries. The latency gate covers named route/method/cache-state/request-mix definitions in the performance manifest, not an agent-selected fast endpoint.
The application deliberately supports one IIS web process and one Windows worker on one host. High availability, IIS web gardens, remote SQLite, and writable multi-node deployment are out of scope.
## 3. Confirmed Decisions
These decisions are fixed unless the user explicitly reopens them.
| Area | Decision |
|---|---|
| Brand | Product UI says GottaGit; solution and assemblies use `GitServer.*` |
| Product scope | Complete standard forge within the explicit exclusions below |
| Audience | Private installation with user and organization namespaces |
| Visibility | Private, internal, and public repositories |
| Public access | Anonymous browse, repository search, clone/fetch, LFS download, blob/archive download for public repositories |
| Runtime | .NET 10, self-contained `win-x64` |
| Web hosting | One IIS application process; Kestrel is supported for development and tests |
| UI | ASP.NET Core MVC, strongly typed Razor views, partials, view components, and native ES modules |
| Database | SQLite on local NTFS, WAL mode, explicit offline migrations |
| Search | SQLite FTS over bounded default-branch text, repositories, issues, and pull requests |
| Worker | Separate `GitServer.Worker` Windows Service with durable SQLite jobs |
| Git | Newest stable x64 Git for Windows resolved at implementation kickoff, pinned and bundled in each release |
| Git engine | Native Git plumbing for transport, reads, mutations, merges, archives, signatures, and maintenance |
| Object formats | SHA-1 and SHA-256 repositories; no 40-character assumptions |
| HTTP transport | Smart HTTP protocol v2 over HTTPS |
| LFS | Batch transfer, locking, integrity validation, associations, usage reporting, and free-space enforcement |
| SSH | Release 1, using Windows OpenSSH and a least-privilege forced-command bridge |
| Repository import | One-time HTTPS or SSH remote import with progress and cancellation; no scheduled mirroring |
| Identity | ASP.NET Core Identity local accounts plus OIDC |
| Provisioning | Administrators create all users; OIDC uses pre-provisioned verified claim linking |
| MFA | TOTP required for system administrators, optional or organization-enforceable for other users |
| Git/API credentials | Scoped, expiring, one-time-displayed PATs; account passwords are not Git credentials |
| Authorization | System admin, organization owner/member, and repository read/triage/write/maintain/admin roles; team and direct grants |
| Setup | The first visitor to the publicly reachable uninitialized site may atomically claim system administrator |
| Browser editor | Multi-file Monaco workspace, draft review, direct commit or branch/PR, and PR conflict resolution; no terminal or extension execution |
| Themes | Port every authorized Files application theme and its theme-specific assets; product shell remains GottaGit |
| Preview modules | Port all safe Files preview concepts, prefer browser sandboxing, and do not bundle FFmpeg |
| Active Git blobs | HTML and SVG can render on a GottaGit Git route only with an opaque CSP sandbox, including direct navigation |
| Markdown | Forge Markdown may contain raw HTML only inside the same opaque sandbox boundary |
| CI/CD | Provider-neutral webhooks, checks, statuses, annotations, and deployment records; no built-in runner |
| Webhooks | One durable worker attempt, no retry; record the outcome |
| Email | In-app notification is authoritative; SMTP is attempted once and a failure is dropped but logged visibly to administrators |
| API | Current versioned REST API with OpenAPI; no compatibility promise between GottaGit releases |
| Repository writes | Direct push and browser commits are allowed unless branch protection blocks them |
| Hooks | System administrators install executables outside repositories; repositories may enable only allowlisted hook IDs |
| Quotas | No owner quota by default; a mandatory configurable free-space reserve blocks new writes before disk exhaustion |
| Retention | Repository and asset soft delete defaults to 30 days; audit retention is fixed at 90 days |
| Backup | Documentation-only, offline, repository-only backup and restore; no full GottaGit recovery feature |
| Secrets | Production operational secrets are plaintext in preserved deployment `appsettings`; strict NTFS ACLs and log redaction are mandatory |
| Malware | No malware scanning |
| Accessibility | Best effort, reported but not a release-blocking WCAG target |
| Distribution | Private proprietary product with complete third-party notices, SBOM, and bundled dependency obligations |
## 4. Explicit Release 1 Scope
### 4.1 Included
| Capability | Required behavior |
|---|---|
| Setup and authentication | First-admin claim, local login, OIDC linking, TOTP/recovery, session management, password recovery, PAT and SSH key management |
| Users and organizations | User profiles, organizations, teams, membership, role grants, invitations created by administrators, ownership transfer |
| Repositories | Create, seed, import, rename, transfer, soft delete, restore, purge, visibility, topics, descriptions, default branch, stars, watches, forks |
| Git HTTP | Clone, protocol-v2 fetch, shallow fetch, push, multi-ref push, branch/tag create/delete, protected-ref enforcement |
| Git LFS | Batch API, upload, download, locking, unlock, verification, deduplication with repository authorization, orphan cleanup |
| Git SSH | Key upload/revoke, clone/fetch/push, forced commands, no shell/PTY/forwarding/SFTP |
| Code browsing | Grid and list modes, tree, blob, raw/download, commits, history, branches, tags, blame, diffs, archive downloads, README rendering |
| Monaco workspace | Multi-file tabs, branch tree, code search, draft changes, diff review, atomic commit, new branch/PR, conflict resolution |
| Rich previews | Image, SVG, video, audio, PDF, Markdown, Office, EPUB, archive, 3D, font, map, subtitle, PSD/PSB, bookmark, text, and fallback concepts where safe and legally available |
| Issues | Markdown, comments, labels, milestones, assignees, mentions, reactions, attachments, templates, links, state transitions |
| Pull requests | Source/target branches and forks, conversation, commits, files, unified/split diff, line comments, suggestions, reviews, CODEOWNERS, checks, conflicts, merge/squash/rebase |
| Branch protection | Required reviews, CODEOWNERS, checks, signatures where configured, force-push/delete policy, current-actor enforcement across every write path |
| Releases | Draft/prerelease, existing or new tag, release notes, generated notes, assets, checksums, download authorization |
| Integrations | Provider-neutral webhook subscriptions, commit statuses, check suites/runs, annotations, deployment records |
| Search | Permission-filtered repositories, bounded default-branch code, issues, and pull requests with honest skipped-file reporting |
| Notifications | In-app inbox and one-attempt SMTP delivery for relevant issue, PR, review, mention, release, and administration events |
| Activity and insights | Real activity stream plus Git-only commit activity, contributors, branches, tags, languages, and repository-size metrics |
| Administration | Users, organizations, repository reconciliation, job failures, storage, free-space reserve, settings, hooks, audit, diagnostics, retention, and health |
| REST API | Versioned current API for supported forge operations, PAT scopes, pagination, validation, idempotency where mutations require it, and OpenAPI |
| Deployment | IIS, Windows worker, OpenSSH bridge, ACLs, HTTPS validation, SQLite migration, pinned Git, health checks, install/update/uninstall scripts |
### 4.2 Excluded
The following must not appear in production navigation, routes, API descriptions, or enabled controls:
- Package registries.
- Wiki.
- Projects, roadmaps, and custom planning fields.
- Discussions.
- Pages or static site hosting.
- Built-in CI runner or execution of repository-controlled jobs.
- Web terminal, language servers, arbitrary Monaco/VS Code extensions, or server-side development containers.
- Scheduled pull mirrors or bidirectional mirrors.
- Arbitrary repository-uploaded Git hooks.
- Multi-node or IIS web-garden operation.
- Full backup of SQLite, LFS, attachments, releases, secrets, keys, settings, issues, or pull requests.
- Malware scanning.
- API compatibility with prior GottaGit releases.
If a concept screenshot contains an excluded item, omit it. Do not show a disabled or `coming soon` version.
## 5. Reference Projects And Reuse Boundary
### 5.1 Files
Primary source: `C:\Projects\files`
Port selectively from these areas after an agent records source, destination, dependency, and license/provenance:
- `Files\Views\Shared` for layout, partial, dialog, breadcrumb, toolbar, and view-component patterns.
- `Files\wwwroot\css\files.tokens.css` and `files.themes.css` for tokens and all authorized themes.
- `Files\wwwroot\js\files.theme.js` for theme behavior, renamed and adapted to authenticated per-user preferences.
- `Files\Services\Modules`, `Files\Views\Shared\FileModules`, and `Files\ViewComponents` for the module registry and viewer composition model.
- Files grid/list, responsive, context-menu, keyboard, touch, lazy-thumbnail, and import-map patterns.
- Monaco assets, language resolution, and locally served editor integration.
- `tests\Files.PlaywrightTests` for Playwright host and smoke-test patterns.
Do not port these as GottaGit infrastructure:
- `FileStorageService`, physical folder mutation, deleted-loose-file model, or Windows path semantics for Git tree paths.
- JSON persistence, bootstrap administrator, folder-password security, public-write defaults, in-memory correctness locks, archive tokens, or process-local rate limiting.
- Static/raw loose-file routes.
- FFmpeg executable.
- Any code path that maps a Git path to an extracted working directory.
Every ported theme and vendor asset is authorized by the user, but the release still needs a provenance inventory, third-party license material, and an SBOM.
### 5.2 Bonobo.Git.Server
Reference: `C:\Projects\Bonobo.Git.Server`
This folder is a precompiled .NET Framework 4.6 Bonobo 6.5.0 deployment, not a source checkout. Use it and upstream Bonobo behavior only as conceptual reference for:
- Bare repositories under a configurable root.
- Smart HTTP service routes.
- Native `upload-pack` and `receive-pack` behavior.
- Repository permissions, teams, administrators, import/reconciliation, hooks, and push identity context.
Do not copy or recreate:
- System.Web MVC 5, OWIN, Unity, EF6, SQLite schema probing, custom NTLM, old cookie security, or default credentials.
- Git 1.9.5, LibGit2Sharp 0.23, manual pack parsing, synchronous request buffering, unsafe Markdown/HTML, or full-table permission scans.
- Bonobo route authorization, password reset, exception disclosure, repository-path construction, or push audit implementation.
### 5.3 Concept Images
Preserve `FilesConvertedToGitServerConcept` unchanged as design evidence.
The four images guide information architecture for repository grid/list, repository code view, pull-request diff, and insights. They are not acceptance evidence and contain no implemented behavior. Remove CodeTower branding and concept data from production.
## 6. Solution Structure
The coordinator creates this structure. No feature agent may add a production project without an explicit architecture decision.
```text
GitServer.slnx
global.json
Directory.Build.props
Directory.Packages.props
NuGet.config
src/
GitServer.Domain/
GitServer.Application/
GitServer.Contracts/
GitServer.Git/
GitServer.Infrastructure/
GitServer.Web/
GitServer.Worker/
GitServer.SshBridge/
GitServer.HookBridge/
GitServer.Admin/
tests/
GitServer.ArchitectureTests/
GitServer.UnitTests/
GitServer.IntegrationTests/
GitServer.GitTests/
GitServer.PlaywrightTests/
GitServer.DeploymentTests/
eng/
versions.json
verify.ps1
package.ps1
evidence.schema.json
deploy/
Install-GottaGit.ps1
Update-GottaGit.ps1
Uninstall-GottaGit.ps1
templates/
docs/
architecture/
operations/
security/
scope/
```
### 6.1 Project Responsibilities
| Project | Responsibility | Forbidden dependencies |
|---|---|---|
| `GitServer.Domain` | Entities, value objects, lifecycle states, permission vocabulary, invariants, domain events | ASP.NET Core, EF Core, SQLite, filesystem, process APIs |
| `GitServer.Application` | Use cases, explicit service interfaces, authorization policy, orchestration, validation | MVC, Razor, EF provider, direct process or filesystem APIs |
| `GitServer.Contracts` | Current REST DTOs, OpenAPI-facing models, webhook/check payload contracts | Persistence entities, MVC views, process APIs |
| `GitServer.Git` | Reviewed native Git command runner, smart HTTP adapter, object/ref/diff/merge/archive/signature operations, hook protocol | EF Core, MVC, user-derived physical paths, shell execution |
| `GitServer.Infrastructure` | EF Core SQLite, Identity stores, NTFS storage, FTS, durable jobs, email/webhook senders, Data Protection, observability adapters | Razor views, controller logic, direct UI concerns |
| `GitServer.Web` | Composition root, authentication, MVC controllers, Razor views/partials/components, REST endpoints, smart HTTP/LFS endpoints, ES modules | Business rules in controllers, direct EF or `Process.Start` calls |
| `GitServer.Worker` | Durable job host for imports, indexing, reconciliation, notifications, webhook delivery, maintenance, retention, and insights | Business-rule duplication, in-memory-only durable work |
| `GitServer.SshBridge` | Forced-command entry point, SSH key identity, exact command parser, current authorization, Git stream bridge | Shell, interactive terminal, arbitrary paths or commands |
| `GitServer.HookBridge` | Central Git pre/post-receive entry point, actor/policy context, event spooling, and exact administrator-hook allowlist execution | Repository-provided executables, shell execution, paths or hook IDs not resolved from protected configuration |
| `GitServer.Admin` | Explicit migration, integrity, reconciliation, setup diagnostics, and release administration CLI | Hidden automatic destructive repair |
### 6.2 Dependency Direction
The table is the complete production `<ProjectReference>` allowlist. An empty cell means no production project reference.
| Project | May reference |
|---|---|
| `GitServer.Domain` | None |
| `GitServer.Contracts` | None |
| `GitServer.Application` | `GitServer.Domain`, `GitServer.Contracts` |
| `GitServer.Git` | `GitServer.Application`, `GitServer.Domain` |
| `GitServer.Infrastructure` | `GitServer.Application`, `GitServer.Domain`, `GitServer.Contracts` |
| `GitServer.Web` | `GitServer.Application`, `GitServer.Contracts`, `GitServer.Git`, `GitServer.Infrastructure` |
| `GitServer.Worker` | `GitServer.Application`, `GitServer.Git`, `GitServer.Infrastructure` |
| `GitServer.SshBridge` | `GitServer.Application`, `GitServer.Git`, `GitServer.Infrastructure` |
| `GitServer.HookBridge` | `GitServer.Application`, `GitServer.Git`, `GitServer.Infrastructure` |
| `GitServer.Admin` | `GitServer.Application`, `GitServer.Git`, `GitServer.Infrastructure` |
`GitServer.Application` owns the interfaces implemented by `GitServer.Git` and `GitServer.Infrastructure`. Those adapter projects do not reference one another. Web, Worker, SshBridge, HookBridge, and Admin are composition roots.
Architecture tests must fail if:
- Domain references ASP.NET, EF, SQLite, filesystem, networking, or process namespaces.
- Application starts a process or opens a repository path directly.
- Any project except `GitServer.Git` and the reviewed deployment test harness invokes Git processes.
- A controller accesses `DbContext`, SQLite, or repository directories directly.
- A feature reaches another feature's EF configuration or internal implementation namespace.
- Production code constructs a filesystem repository path from owner, name, ref, branch, or Git tree path.
- Any production project reference exists outside the exact allowlist above.
### 6.3 Feature Folders
Use the same vertical feature names across Domain, Application, Infrastructure, Web, Worker, and tests:
- Identity
- Organizations
- Repositories
- GitTransport
- Lfs
- Search
- Workspace
- Issues
- PullRequests
- Releases
- Checks
- Notifications
- Activity
- Insights
- Administration
Keep code in a feature unless it is a genuinely shared primitive. Do not add generic repositories, a service locator, MediatR, or a new abstraction merely to avoid a direct and stable application interface.
## 7. Runtime Topology
```text
HTTPS clients
-> IIS / ASP.NET Core Module
-> GitServer.Web
-> MVC/Razor and REST
-> Git smart HTTP adapter
-> LFS API
-> SQLite + local Git/LFS/asset stores
Windows Service
-> GitServer.Worker
-> durable SQLite jobs
-> imports, indexing, notifications, webhooks
-> reconciliation, maintenance, retention, insights
SSH clients
-> Windows OpenSSH
-> dedicated non-admin GottaGit account
-> generated per-key forced command
-> GitServer.SshBridge
-> native git-upload-pack or git-receive-pack
Git receive hooks
-> centrally installed GottaGit hook bridge
-> GitServer.HookBridge
-> branch policy validation before update
-> atomic post-receive event spool after update
-> worker reconciliation
```
The IIS application pool must have one 64-bit worker process and `No Managed Code`. The worker is a separate Windows Service. SQLite and all mutable storage remain on local NTFS.
Web, Worker, SshBridge, HookBridge, and Admin share a cross-process maintenance gate. Update/migration acquires its exclusive side before stopping new HTTP, SSH, hook, job, import, maintenance, or mutation admission; existing bounded operations drain or are terminated before schema/binary changes. IIS overlapped recycle is disabled for this single-node product. A host-instance lease makes a second Web process fail readiness rather than become a second writer.
## 8. Authority And Consistency Model
| Data | Authority | Recovery/consistency rule |
|---|---|---|
| Objects, commits, trees, refs, tags | Bare Git repository | Git is authoritative even if a later metadata job fails |
| Users, OIDC links, PATs, SSH keys | SQLite | Fail closed when unavailable or inconsistent |
| Organizations, teams, grants, visibility | SQLite | Every access path evaluates current state |
| Issues, PRs, reviews, releases, checks | SQLite plus referenced immutable Git OIDs | Optimistic concurrency and explicit stale-ref handling |
| LFS bytes | NTFS object store | SQLite repository association is required for authorization |
| Attachments and release assets | NTFS object store plus SQLite metadata | Atomic same-volume write, hash, then metadata publication |
| Search index | Rebuildable SQLite FTS database | Never authoritative; current ACL filter is mandatory |
| Counts, languages, contributors, activity, insights | Rebuildable derived projection | Show a real stale/unavailable state, never fabricated values |
| Push events | Git refs plus atomic NTFS event spool | Idempotent worker consumption plus periodic ref reconciliation |
| Jobs | SQLite | Leases, idempotency keys, bounded retry where specified, poison state |
### 8.1 Required State Machines
Define, diagram, and test these before implementing their UI:
| Operation | Minimum states |
|---|---|
| Repository creation | Requested -> Provisioning -> Ready or Failed |
| Remote import | Requested -> Cloning -> Validating -> Installing -> Ready or Failed/Cancelled |
| Rename/transfer | Locking -> MetadataReserved -> AliasUpdated -> Complete or RecoverableFailure |
| Delete | Active -> Deleting -> Trash -> SoftDeleted -> Purged |
| LFS upload | Pending -> Streaming -> Verified -> Available or Rejected |
| Release asset upload | Pending -> Streaming -> Verified -> Published or Rejected |
| Search projection | Queued -> IndexingSnapshot -> Current or Stale/Failed |
| Webhook delivery | Pending -> AttemptReserved -> Attempting -> Delivered, FailedFinal, or OutcomeUnknown |
| Email delivery | Pending -> AttemptReserved -> Attempting -> Delivered, FailedFinal, or OutcomeUnknown |
| PR merge | Checking -> Prepared -> RefUpdated -> Finalized or Stale/Failed |
No database transaction may remain open while Git, network, SMTP, webhook, or long filesystem work executes.
### 8.2 Storage Layout
All mutable paths derive from configured roots and service-generated opaque IDs.
```text
DataRoot/
Database/GitServer.db
Search/GitServer.Search.db
Repositories/{shard}/{repository-id}.git
Lfs/{oid-prefix}/{oid}
Attachments/{opaque-id}
ReleaseAssets/{opaque-id}
Drafts/{opaque-id}
Previews/{renderer-version}/{object-format}/{oid}
GitEvents/Inbox
GitEvents/Processing
Trash
Temp
DataProtection
Logs
```
Rules:
- Reject network shares, synchronized folders, reparse points, junctions, and unexpected symlinks for managed storage.
- Never use an owner name, repository name, ref, Git path, original attachment name, or user ID as a physical filename.
- Never extract a Git tree to browse it.
- Write objects and assets to a generated same-volume temporary file, hash and flush it, then atomically rename.
- Resolve a URL slug through SQLite to an immutable repository ID before finding a repository path.
- Use Git-native path semantics for tree entries; do not apply Files/Windows filename rules to Git paths.
- Keep deployment binaries and plaintext production `appsettings` outside `DataRoot`; preserve both during update.
### 8.3 Storage Admission And Disk Reserve
One cross-process `IStorageAdmission` service protects two configured nonzero floors: the user-data free-space reserve and a smaller control-plane headroom that user operations can never reserve. It uses short SQLite reservation records with leases plus current volume measurements. Every user/data byte-producing path must acquire admission before opening its destination and release/settle it afterward.
The gate covers HTTP and SSH receive-pack, LFS, attachments, release assets, Monaco drafts/merge state, remote import, repository seed/fork, archive/preview temporary files, Git maintenance/repack, search/SQLite WAL growth, event spool, and trash moves.
- W0 freezes nonzero maximum input/reservation values for each operation from the small-team envelope and W1 proves them. Production configuration may reduce them but may not set them to zero/unbounded.
- LFS and HTTP uploads reserve the declared bounded size before reading the body.
- HTTP/SSH pushes preflight before launching receive-pack. Because SSH does not declare pack size, it reserves the configured maximum accepted push size; native `receive.maxInputSize` enforces the same ceiling.
- Imports and maintenance reserve a documented worst-case amount based on configured maximum or current repository size and an expansion factor.
- A monitor checks free space while long writes run. Crossing the reserve cancels the operation, kills its Git process tree, and removes quarantine/temp data; it does not wait until pre-receive.
- Pre-receive rechecks policy and reserve validity but is defense in depth, not the first disk guard.
- When admission is unavailable, reads remain available and writes fail with a controlled, observable result.
- Simultaneous HTTP/SSH pushes and non-Git uploads must not overbook the same free bytes.
- Admission requires projected free space to remain above `UserDataReserve + ControlPlaneHeadroom`. The reservation row itself is a bounded control-plane write and cannot consume user-data budget.
- Only bounded reservation/settlement, audit/security failure, maintenance-lock, process-cancellation, queue-state, and cleanup records may use control-plane headroom. No repository, LFS, asset, preview, search payload, normal telemetry, or user content may use it.
- Cap and rotate file logs, bound event-spool files/count, bound SQLite WAL size/checkpoint age, and provide Windows Event Log fallback for a final disk-critical operator alert. At the control-plane floor, fail readiness and stop all new writes while still attempting bounded cleanup/cancellation.
- Reservation leases heartbeat. Failure to renew cancels/kills the associated writer before its reservation can expire; stale reservations are reclaimed only after proving no owning process/operation remains.
- W0 freezes numeric user reserve, control headroom, WAL/log/spool caps, heartbeat, cancellation, and cleanup limits; W1 tests crash recovery at each boundary.
## 9. Git Data Plane
### 9.1 Bundled Runtime
Wave 0 resolves the newest stable official x64 Git for Windows release on that date and writes its exact version, artifact URL, SHA-256, license/source location, and extraction manifest to `eng/versions.json`. Builds and releases use that pin. Runtime startup never downloads `latest` and never trusts machine `PATH`.
Each GottaGit release may update Git only after all Git, LFS, SSH, hook, and repository-format tests pass against the new pin. The server tests only the current pinned Git client release as confirmed by the user.
### 9.2 Git Runner Invariants
All Git execution uses one reviewed `IGitCommandRunner` implementation in `GitServer.Git`:
- Absolute bundled executable path.
- `UseShellExecute = false` and `ProcessStartInfo.ArgumentList`.
- No `cmd.exe`, PowerShell, shell concatenation, aliases, arbitrary executable names, user credential helpers, editors, pagers, or prompts.
- Minimal environment with system/global Git configuration disabled unless an operation explicitly supplies a reviewed config file.
- `GIT_TERMINAL_PROMPT=0`, fixed locale/machine-readable formats, and external diff/textconv/filter execution disabled.
- Concurrent stdin, stdout, and stderr pumping with backpressure.
- Bounded diagnostics and result sizes; no unbounded `ReadToEnd`, `byte[]`, string, or JSON materialization.
- Operation-specific wall-clock timeout, idle timeout, cancellation, queue limit, and output cap.
- Complete descendant-process termination on abort, timeout, recycle, or service shutdown.
- Structured operation type, duration, exit code, timeout, and redacted diagnostic logging.
- Literal pathspecs and `--` boundaries where tree paths are accepted.
- Exact allowlist of commands and options per application operation.
SshBridge invokes upload-pack/receive-pack through this same runner; it does not launch Git directly. An architecture test must reject direct process creation outside the exact `GitServer.Git` runner file, the exact constrained administrator-hook runner file in `GitServer.HookBridge`, and non-production deployment test fixtures.
The administrator-hook runner is not a general process API. It accepts only an immutable hook ID, resolves that ID to an absolute executable plus fixed administrator-configured arguments from ACL-protected deployment configuration, rejects user/repository-supplied paths/arguments, never uses a shell, supplies a minimal environment and bounded stdin, captures bounded diagnostics, enforces timeout/cancellation/process-tree termination, and records audit. Repository users can enable an ID but cannot define or alter its executable, arguments, identity, or environment.
### 9.3 Smart HTTP
Use the bundled native Git HTTP backend or its exact native upload/receive service entry points behind a reviewed adapter. Wave 1 must prove the chosen adapter on IIS before contracts freeze. The final route surface exposes only:
- `GET /{owner}/{repository}.git/info/refs?service=git-upload-pack`
- `GET /{owner}/{repository}.git/info/refs?service=git-receive-pack`
- `POST /{owner}/{repository}.git/git-upload-pack`
- `POST /{owner}/{repository}.git/git-receive-pack`
Requirements:
- Authenticate and authorize read or write before launching Git.
- Public repositories permit anonymous upload-pack only.
- HTTP Basic carries username plus PAT; browser password authentication is rejected for Git.
- Forward `Git-Protocol` for protocol v2.
- Stream request and response without ASP.NET form parsing or complete-body buffering.
- Return Git media types and protocol-appropriate status/errors, never an HTML login redirect.
- Route no dumb-HTTP object paths and expose no bare repository directory through IIS static files.
- Apply one global cross-process five-RPC limit shared by IIS and SSH, a bounded waiting queue, per-user limits, and per-repository mutation coordination.
- Enable receive/fetch object validation and leave permissive arbitrary-object upload settings disabled.
- Recheck protected-ref policy inside pre-receive, not only before service advertisement.
### 9.4 LFS
Implement the Git LFS Batch API, basic transfer, locking API, verification, repository associations, and cleanup.
- LFS OIDs are SHA-256 regardless of repository object format.
- Stream uploads through hash and size validation to temporary storage.
- A globally deduplicated object is downloadable only when the current repository is associated with it and the actor can read that repository.
- Lock operations use optimistic concurrency and audit the actor.
- Concurrent uploads of the same OID are idempotent.
- Interrupted, wrong-size, wrong-hash, unauthorized, and disk-reserve failures leave no available partial object.
- No owner quota is imposed by default; the global free-space reserve applies before accepting bytes.
- Soft deletion and reachability-aware cleanup retain objects still referenced by another repository.
### 9.5 SSH
Use the Windows OpenSSH Server serviced by Windows Update. Do not implement SSH protocol or cryptography in GottaGit.
- Create one dedicated enabled local non-administrator account used only by the forge SSH endpoint.
- Disable passwords, shell, PTY, SFTP, SCP, agent forwarding, port forwarding, X11, tunneling, and user startup files.
- The worker atomically regenerates an ACL-protected `authorized_keys` file from canonical active keys because inbox Windows OpenSSH does not provide a supported `AuthorizedKeysCommand` contract.
- Each key line contains a generated fixed-format key ID in a forced command plus restrictive key options.
- The bridge rechecks key status, user status, repository identity, visibility, and current read/write permission in SQLite on every connection.
- Parse only exact `git-upload-pack 'owner/repository.git'` and `git-receive-pack 'owner/repository.git'` forms from `SSH_ORIGINAL_COMMAND`.
- Never pass submitted owner/repository text directly to a filesystem path.
- Invoke bundled Git through the shared `IGitCommandRunner` without a shell and stream binary stdin/stdout/stderr.
- Preserve stable SSH host keys across updates. Their loss is accepted by the repository-only backup policy and must be documented.
Tests must prove that shell commands, malformed quoting, alternate binaries, drive/UNC paths, traversal, control characters, PTY, SFTP, SCP, and every forwarding mode fail.
### 9.6 Branch Protection And Push Events
One `IBranchPolicy` application service is used by HTTP receive-pack hooks, SSH receive-pack hooks, Monaco commits, PR merges, branch deletion, and force-push operations.
Pre-receive evaluates:
- Authenticated pusher, distinct from commit authors and committers.
- Exact old/new OIDs and deletion/create/update type.
- Fast-forward, force-push, delete, required review, CODEOWNERS, required check, signature, and repository-lifecycle rules.
- Free-space reserve and operation limits.
- Object validation and ref-name rules using pinned Git.
After refs change, Git is authoritative. Post-receive atomically writes an event file to `GitEvents/Inbox`; the worker consumes it idempotently and refreshes search, activity, PR state, counts, and notifications. A periodic reconciler compares Git refs with derived metadata to recover an event lost before spooling. Never tell a client a successful ref update was rolled back because post-processing failed.
## 10. Identity And Authorization
### 10.1 Identity
- Use ASP.NET Core Identity with current recommended password hashing and security-stamp validation.
- Persist Data Protection keys under `DataRoot/DataProtection` with restrictive ACLs so cookies survive IIS recycle.
- Support local login and configured OIDC providers.
- Administrators pre-create every account. OIDC links by administrator-entered provider/subject or a single audited verified-email link permitted for that pre-created account.
- Require TOTP and recovery codes for system administrators. Organizations may require MFA for members.
- Store PAT secret verifiers one-way with lookup prefix, scopes, mandatory non-null future expiry, revocation, last-used metadata, and one-time display. Default lifetime is 90 days and administrators may configure a maximum up to 365 days.
- Store canonical SSH public key material, supported algorithm, SHA-256 fingerprint, owner, created/last-used data, and revocation state. Enforce fingerprint uniqueness.
- Store Git signing keys separately from SSH authentication keys. Support canonical GPG and SSH signing public keys, an ownership challenge signed by the private key, fingerprint uniqueness, created/revoked timestamps, and audit history.
The uninitialized public setup page intentionally allows the first visitor to claim system administrator. Implement the claim as one atomic SQLite transition. Concurrent requests must produce exactly one pending administrator and permanently close public claiming. The winning setup session completes password, TOTP, recovery-code acknowledgement, and activation before normal administration. If that session is irretrievably lost, a local server administrator may run an audited `GitServer.Admin recover-setup` command only while no administrator has completed activation. Show an explicit first-run takeover warning in installation documentation and the setup UI; do not invent a token requirement for the initial public claim.
Administrator-created local users start inactive. Creation produces a hashed, expiring, one-use activation credential that is displayed once for manual delivery; SMTP may also attempt delivery but is not required. Activation sets the initial password, completes required MFA, rotates the security stamp, and consumes the credential atomically. Interrupted activation can resume while the credential remains valid. Unknown OIDC subjects and public registration always fail.
### 10.2 Permission Model
Repository capabilities include at least:
- Read.
- Triage issues and pull requests.
- Write Git and collaboration content.
- Maintain repository settings and branch policy.
- Administer grants, transfer, and delete.
Resolve capability from system role, owner type, organization membership, team grants, direct grants, repository visibility, and current account state. Deny by default.
Visibility semantics are fixed:
- Public grants anonymous read and authenticated read but never mutation.
- Internal grants read to every active authenticated installation user but never mutation.
- Private grants no implicit installation-wide access; read requires system administration, organization ownership where applicable, or a team/direct repository grant.
- Organization membership alone does not grant private repository read unless an organization policy creates an explicit team/default grant.
- Visibility never grants triage, write, maintain, or admin capability.
Use the same authorization service for MVC, REST, smart HTTP, SSH, LFS, archives, raw blobs, preview data, search, workspace commits, PR merges, release assets, and worker jobs. UI visibility is never an authorization boundary.
Private repository lookups must use one consistent non-disclosing response across HTML, REST, Git HTTP, SSH, search, autocomplete, activity, counts, and errors. Internal repositories use that same non-disclosing behavior for anonymous, inactive, disabled, and unknown OIDC actors; only an active authenticated installation user can distinguish/read an internal repository.
### 10.3 Browser Security
- Require HTTPS, secure/HttpOnly cookies, HSTS, explicit canonical external URL, and validated forwarded headers from configured proxies only.
- Apply antiforgery validation to every cookie-authenticated mutation. Git and bearer-token endpoints use their own authentication and do not require browser antiforgery tokens.
- Use encoded Razor output by default for names, paths, authors, messages, refs, comments, snippets, and diffs.
- Use a strict application CSP with no production `unsafe-eval`; Monaco worker policy must be explicitly tested.
- Set `X-Content-Type-Options: nosniff`, frame restrictions for the application shell, referrer policy, and safe link schemes.
- Never trust request `Host` when generating clone, OIDC, webhook, or email links.
- Mark private responses non-public and prevent IIS/proxy output caching from crossing principals.
### 10.4 Sandboxed Active Content
The user requires inline raw HTML and SVG on Git routes. Preserve that functionality without granting application-origin privileges:
- Every active blob response, including direct navigation, receives a CSP `sandbox` directive that creates an opaque origin.
- The sandbox may allow scripts only inside the opaque frame/document. It must not allow same-origin, top navigation, forms, popups, downloads without user activation, or parent DOM access.
- The viewer uses a sandboxed iframe and an immutable blob-OID URL.
- Repository-relative images/media resolve through authorized Git blob endpoints; external loads follow explicit CSP/referrer policy.
- The application shell never inserts rendered repository HTML into its own DOM.
- Forge Markdown with raw HTML renders through this sandbox boundary rather than `Html.Raw` in the application document.
- Stored-XSS tests must prove pushed content cannot read app cookies/storage, fetch authenticated pages as the parent origin, extract antiforgery tokens, navigate the parent, or execute in the application document.
This is not static site hosting and exposes no arbitrary filesystem directory.
### 10.5 PAT Scopes
W2 freezes a PAT-scope-to-capability matrix using this minimum vocabulary:
| Scope | Maximum operations, still limited by current repository/organization permission |
|---|---|
| `repo:read` | Git fetch, repository metadata, code/history/archive/raw/LFS reads |
| `repo:write` | Git push, LFS write/locks, browser commits/branches |
| `repo:admin` | Repository settings, grants, hooks, transfer/delete |
| `issues:read`, `issues:write` | Issue/comment/label/milestone read or mutation |
| `pull_requests:read`, `pull_requests:write` | PR/review/comment/merge read or mutation |
| `releases:read`, `releases:write` | Release/tag metadata and asset read or mutation |
| `checks:read`, `checks:write` | Status/check/deployment read or publication |
| `user:read` | Current-user profile/key/token metadata allowed by endpoint |
| `org:read`, `org:admin` | Organization/team read or administration |
| `admin` | System administration; issuable only by and to an active system administrator |
A scope can only narrow authority; it never grants an underlying role/capability. Git HTTP maps upload-pack to `repo:read` and receive-pack to `repo:write`. LFS maps read/write/lock operations accordingly.
Use an injectable UTC clock for expiry. REST, Git HTTP, and LFS reject an expired token on the next operation without a grace cache; integration tests cover just-before/at/after expiry and do not require revocation to enforce it.
### 10.6 Confirmed Security Tradeoffs
- No malware scanner is called. Documentation must state that authorized Git, LFS, attachment, and release content may contain malware.
- Operational secrets remain plaintext in deployment `appsettings`. Real secrets must never enter source control, publish templates, logs, test artifacts, diagnostics, or UI. Installer ACL tests are release-blocking.
- Administrator-approved hooks execute trusted administrator-installed code. Hook binaries and configuration are not writable by repository users or the SSH account. Apply timeout, environment, logging, and process-tree limits.
- Webhooks and email have at most one attempt. Persist an immutable attempt ID and `AttemptReserved` state before network I/O. Once `Attempting` begins, lease recovery may only mark `OutcomeUnknown`; it must never send again. Failure or ambiguity must be observable but is not retried.
## 11. SQLite, Jobs, And Search
### 11.1 SQLite
Use two local SQLite files:
- `GitServer.db` is authoritative for Identity and forge metadata.
- `GitServer.Search.db` is a disposable FTS projection and can be rebuilt.
Apply and verify connection settings on every connection:
- Foreign keys enabled.
- WAL mode.
- Bounded busy timeout and bounded retry with jitter.
- `synchronous=FULL` for the authoritative database.
- Short write transactions.
- UTC timestamps and explicit optimistic concurrency tokens.
Never share connection/command/reader instances across threads. Never wait for Git, SMTP, webhooks, or file transfer inside a transaction. Return a bounded failure rather than retrying `SQLITE_BUSY` indefinitely.
`GitServer.Admin migrate` is the only production migration entry point. Web and worker startup must refuse an unknown, newer, partially applied, or pending schema. Upgrade first acquires the shared maintenance gate, rejects new HTTP/SSH operations and job claims, drains Git processes, stops the worker, runs migration once, and starts matching binaries. Do not auto-migrate in Web or Worker.
### 11.2 Durable Jobs
The SQLite queue includes job type, versioned payload, state, attempts, immutable delivery-attempt ID where applicable, lease owner/expiry, idempotency key, not-before time, timestamps, and final diagnostics.
Retries are allowed for internal idempotent work such as import phases, indexing, reconciliation, maintenance, retention, and preview projection. Webhook and SMTP jobs reserve exactly one attempt. `FailedFinal` is used only when no payload could have been accepted or an explicit failure response proves rejection. Timeout/reset after transmission begins, uncertain SMTP acceptance after `DATA`, or a crash after `Attempting` begins produces `OutcomeUnknown` and no retry. Explicit HTTP failure responses and SMTP rejection responses produce `FailedFinal`; confirmed HTTP success or SMTP acceptance produces `Delivered`. Poison jobs appear in administration and never spin indefinitely.
### 11.3 Search
Index repository name/description/topics, bounded text content from the default branch, issues, and pull requests.
- Key entries by immutable repository ID and exact indexed commit OID.
- Parse and escape FTS syntax; do not forward arbitrary input directly to `MATCH`.
- Define configurable maximum text size, binary detection, excluded/generated directories, maximum indexed files, query length, result count, and snippet size.
- Report skipped files honestly in administration and repository indexing status.
- Encode snippets as untrusted text.
- Filter candidates, snippets, totals, facets, and autocomplete by current authoritative permission before returning data.
- Visibility or permission revocation takes effect immediately even when the FTS projection is stale.
- Rebuild after restore/import, repository transfer/delete, or detected inconsistency.
A required regression test leaves private content deliberately stale in FTS, revokes access, and proves no title, path, snippet, count, facet, autocomplete entry, or distinguishable status leaks.
## 12. UI And Files Port
### 12.1 Composition
Use strongly typed MVC views with feature-local partials and view components. Controllers bind, authorize, call an application use case, and map a view model. They do not calculate business state or read Git/SQLite directly.
Required reusable components include:
- Application shell and responsive sidebar.
- Repository and global tab navigation.
- Toolbar, breadcrumbs, search, command/dialog surfaces, context menus, toasts, and confirmations.
- Grid/list switcher used for repository lists and Git tree/blob browsing where applicable.
- Repository card, file card, file row, commit row, ref selector, status badge, permission badge, user/avatar, empty/error/loading states.
- Issue/PR timeline, comment, review thread, diff file, check suite, release, activity, insight chart, audit row, and pagination components.
- Monaco shell, tab strip, file explorer, source control changes, diff review, and conflict panel.
Persist theme and grid/list preferences per authenticated user; anonymous preferences may use local storage. Do not carry the `files:` storage key or Files branding.
### 12.2 Grid, List, And Rich Previews
Both repository dashboards and repository tree browsing support real grid and list modes. Grid cards may show immutable blob thumbnails; list rows show Git metadata. Neither mode checks out files.
Adapt `IFileModule` into an `IBlobViewerModule` selected from repository ID, object format, blob OID, path, detected type, size, and actor authorization. A module receives a bounded authorized stream/URL, never a local filesystem path.
Rules:
- Use blob OID ETags and immutable cache keys.
- Lazy-load previews with bounded browser concurrency.
- Prefer browser workers/iframes for Office, EPUB, archive, 3D, PSD/PSB, subtitle, map, and similar complex parsing.
- Never execute a repository filter, macro, script, binary, language server, build, or preview helper in IIS/Worker.
- Do not bundle FFmpeg. Use browser-native audio/video behavior and safe bounded metadata.
- Apply configurable module size limits. When exceeded, show real type/size/OID data plus source, raw, or download actions; do not pretend a thumbnail exists.
- Never extract archives on the server.
### 12.3 Monaco Workspace
Monaco is a locally pinned dependency and must not call a CDN.
The workspace supports:
- Authorized tree and blob loading by immutable OID.
- Multiple text-file tabs, language detection, search, and unsaved-state warning.
- A server-side draft based on an exact base commit with file add/edit/delete/rename operations.
- Diff review of every change before commit.
- Direct commit when allowed, or creation of a branch and PR.
- Atomic ref update against the expected old OID.
- Three-way PR conflict presentation, editable result, revalidation, and resolution commit to the source branch.
Use Git plumbing and a temporary index; do not create a persistent server working tree. Reject unsupported binary edits, submodule target editing, symlink writes, NUL paths, invalid Git paths, oversized editable blobs, and stale base commits with an actionable real conflict response.
No terminal, extension host, arbitrary worker, language server, package install, build, test, or repository code execution exists.
### 12.4 Concept Fidelity
Use Files as the component and theme authority. Use concept screenshots as Git information-architecture guidance.
- Repository screen: real search, grid/list, import/create, visibility, language, branch, activity, star, and lock/protection state.
- Code screen: real clone URLs, tabs, tree/list, latest commit, README, language data, contributors, PR/check summaries.
- PR screen: real source/target, review actions, overview/conversation/commits/files/checks, unified/split diff, sidebar metadata, and merge result.
- Insights screen: real Git-only metrics. Omit issue/PR/CI/deployment charts because Git-only insights were confirmed.
Do not preserve CodeTower name, sample repositories, sample people, sample hashes, static charts, or inconsistent navigation labels.
## 13. Forge Feature Rules
### 13.1 Repositories
- URLs use user-or-organization owner plus repository slug, while storage uses immutable IDs.
- Name uniqueness is case-insensitive within an owner; preserve display casing and canonical redirects.
- Creation may be empty or seed an initial README, selected license, `.gitignore`, default branch, description, visibility, and LFS patterns.
- Seed content is a real initial commit authored by the requesting user and optionally server-signed when configured.
- Remote import supports reviewed HTTPS and SSH schemes, host allowlists, credential cleanup, SSH host-key pinning, cancellation, progress, object validation, and no silent trust-on-first-use.
- Forks maintain an explicit network, compatible object format, inherited visibility constraints, upstream relationship, sync operation, and cross-fork PR authorization.
### 13.2 Issues
Implement issue numbers scoped to repository, title/body, open/closed state, comments, labels, milestones, assignees, mentions, reactions, attachments, templates, cross-references, author/editor timestamps, and optimistic concurrency. Every mutation creates the appropriate activity, audit, and notification records.
### 13.3 Pull Requests
Implement source repository/ref, target repository/ref, merge base, state, draft state, commits, computed files, reviews, decisions, threaded line comments, suggestions, labels, milestone, assignees, reviewers, CODEOWNERS, check requirements, conflicts, and related issues.
Diffs support text/binary distinction, rename/copy metadata where native Git provides it, whitespace settings, unified/split display, pagination, and configurable byte/line/file limits. Oversized content reports exact metadata and offers raw/download/local-review paths rather than fake truncated completeness.
Merge/squash/rebase must:
- Re-evaluate current authorization and branch policy.
- Re-evaluate required checks/reviews and exact target/source OIDs.
- Use native Git in bounded temporary state.
- Atomically update the target ref with the expected old OID.
- Fail cleanly as stale if a ref moved.
- Record actual merge OID, authenticated actor, strategy, and audit event.
### 13.4 Releases
Support draft, prerelease, title/body, existing or newly created tag, generated notes, assets, checksums, publish/unpublish, and authorization. Assets use opaque storage, hash verification, free-space guard, and 30-day soft-delete behavior.
### 13.5 Checks, Deployments, And Webhooks
The provider-neutral API supports commit statuses, check suites, check runs, annotations, details/log URLs, required-check contexts, and deployment records. It does not execute jobs or store CI artifacts/log streams.
Webhooks use event subscriptions and HMAC signatures. Enforce target scheme/host policy, DNS/IP checks, timeout, bounded response capture, secret redaction, and one durable at-most-once attempt. The UI shows `Delivered`, `Failed`, or `Outcome unknown`; it provides no retry/replay control.
### 13.6 Notifications And Activity
Create one authoritative in-app notification record per applicable event and one optional SMTP job. SMTP attempts at most once. A failed or unknown outcome does not roll back the action or notification and is surfaced to administrators.
Activity and audit distinguish authenticated actor from Git author/committer. Never treat pushed commit identity as authenticated identity.
### 13.7 Signatures
Use native Git to verify supported GPG and SSH commit/tag signatures.
Trust and display states are distinct:
- `Verified` means the signature is cryptographically valid and its active, ownership-proven signing key is registered to the displayed GottaGit signer.
- `ValidUntrusted` means cryptographically valid but the key is unknown, revoked, unproven, or not mapped to that signer.
- `Invalid`, `Unsigned`, and `VerificationUnavailable` are explicit states.
Generate the native SSH allowed-signers input and GPG trust/keyring input only from current GottaGit signing-key records. A revoked key cannot satisfy future protected-branch pushes even if an old signature remains cryptographically valid. Preserve audit history so old UI can distinguish validation observed before/after revocation without claiming current trust.
Optional server signing for browser commits/tags is enabled only when a system administrator configures a dedicated ACL-protected signing key and identity. It is never the SSH host key or a user's authentication key. Branch policy may require `Verified`; W2 freezes exact policy for merge commits, tags, bots, and server-signed browser commits.
## 14. REST API Rules
- Use `/api/v1` and publish current OpenAPI from executable endpoint metadata.
- Use PAT bearer authentication with explicit scopes; cookie-authenticated browser calls retain antiforgery protection.
- Apply the same application services and authorization as MVC and Git transports.
- Use consistent validation/problem details, bounded pagination, idempotency keys for retry-prone create operations, and concurrency tokens for mutable resources.
- Never serialize EF entities or physical paths.
- The API has no cross-release compatibility promise. Each release validates only its current OpenAPI and generated client smoke test.
- Release notes must call out breaking API changes honestly.
Before W2 closes, `docs/scope/api-capability-matrix.md` must list every in-scope REST resource/action, required PAT scope, repository/organization capability, anonymous behavior, idempotency/concurrency requirement, pagination/limit, and vertical-slice test ID. An endpoint is not optional merely because a feature agent omitted it from OpenAPI; the confirmed feature matrix and this capability matrix are the external completeness authority.
## 15. Operations And Deployment
### 15.1 Installer
`Install-GottaGit.ps1` is idempotent and must:
- Verify supported x64 Windows Server, administrator rights, local NTFS data root, and free space.
- Enable/verify IIS and ASP.NET Core Module requirements for self-contained ASP.NET Core hosting.
- Enable/verify Windows OpenSSH Server and validate effective `sshd` configuration.
- Create dedicated IIS, worker, and SSH identities with least-privilege ACLs.
- Configure one 64-bit `No Managed Code` app pool, site/bindings, HTTPS requirements, request limits, startup/recycle/shutdown settings, no web garden, and no overlapped recycle.
- Install and start the Windows worker.
- Install the SSH forced-command bridge, dedicated endpoint/account, generated key location, host keys, and forwarding/shell restrictions without changing unrelated SSH accounts.
- Install `GitServer.HookBridge` and administrator-approved hook configuration under protected non-repository paths; repository users and the SSH identity have no write access.
- Create external data layout and ACLs.
- Place configuration templates without overwriting preserved production `appsettings`.
- Validate the bundled Git version/checksum and no dependency on machine `PATH`.
- Leave the site in an uninitialized state where the first visitor may claim administration.
`Update-GottaGit.ps1` must acquire the cross-process maintenance gate, make Web and SshBridge reject new operations, stop new Worker claims, drain/terminate bounded Git operations, stop Worker, preserve data and deployment appsettings, run explicit migration, switch versioned binaries, validate ACLs/configuration, restart, release maintenance, and run readiness checks. Tests must race HTTP push, SSH push, Worker claim, and update to prove no operation begins inside the migration window.
`Uninstall-GottaGit.ps1` must explicitly ask whether to retain repositories/data and must not remove unrelated IIS/OpenSSH configuration.
### 15.2 Configuration And Secrets
Ship safe templates only. Production secrets remain plaintext in the deployment `appsettings` chosen by the user.
- Never commit real secrets.
- Installer applies restrictive ACLs and rejects broad write/read access.
- Publish/update preserves the production file.
- Redact Authorization, cookies, PATs, OIDC secrets, SMTP credentials, hook secrets, signing material, SSH private keys, import credentials, and URL userinfo from logs/errors/evidence.
- Use explicit canonical HTTPS URL and trusted-proxy configuration.
- Keep Data Protection and SSH host keys out of web content.
### 15.3 Repository-Only Backup
Provide `docs/operations/repository-backup.md`, not a full backup tool or UI.
The documented procedure stops IIS, Worker, and SSH Git access, waits for Git processes to exit, copies only `DataRoot/Repositories`, restarts services, and verifies restored repositories with native Git.
The document must state prominently that this does not preserve:
- SQLite users, organizations, permissions, issues, PRs, reviews, releases, checks, settings, audit, jobs, or repository metadata.
- LFS content, attachments, release assets, drafts, previews, or search.
- Deployment appsettings/secrets, Data Protection/signing keys, SSH user keys, or SSH host identity.
Restore means installing a fresh GottaGit instance and using the local-only administrative ingestion command once for each copied repository:
```powershell
GitServer.Admin repositories ingest `
--source "D:\RepositoryBackup\opaque-repository.git" `
--owner "new-owner" `
--name "new-name" `
--visibility private `
--copy
```
This command is not exposed through Web/REST. It requires local administrator rights, acquires the exclusive maintenance gate, and is disabled unless a completed first administrator and the requested destination user/organization already exist. The operator-supplied source must be a canonical local fixed-NTFS path outside managed destination storage, readable under the operator account, with no reparse point/junction/symlink in its ancestry; the command opens it read-only. It accepts an explicit new owner/name because the repository-only backup intentionally loses that metadata. It validates a bare repository with pinned Git, detects object format, runs strict object checks, ignores/removes source hooks and unsafe local configuration, copies to a same-volume temporary managed path, installs GottaGit configuration/hooks, creates fresh private SQLite metadata, and atomically publishes the repository. It never executes content from the source repository.
LFS pointers remain in Git, but their LFS object content is lost unless independently preserved outside GottaGit's supported backup procedure.
An automated deployment test must execute the documented repository copy/import steps and compare refs and `git fsck`; it must not claim full product recovery.
### 15.4 Observability
- Structured rolling logs with correlation, operation, repository ID, actor ID, duration, result, and bounded redacted diagnostics.
- Separate durable 90-day security/administrative audit records in SQLite.
- OpenTelemetry traces and metrics for HTTP, jobs, Git processes, SQLite contention, FTS lag, queue depth, disk reserve, LFS, SMTP, webhook, and SSH bridge.
- Liveness and readiness endpoints. Readiness verifies schema compatibility, database access, repository root, free-space reserve, key/config availability, worker expectations, and pinned Git health without public detail leakage.
- Admin diagnostics show failures and staleness, never secret values or repository contents.
## 16. AI Development Operating Model
### 16.1 Coordinator Authority
One main agent is the coordinator. It owns:
- The decision ledger and scope matrix.
- Todo state and dependency gates.
- Git initialization, branches/worktrees, and integration order.
- Shared project/composition files and migrations.
- Subagent prompts, file ownership, and acceptance criteria.
- Review of every subagent diff before integration.
- Final build/test/package evidence.
The coordinator must continue through implementation, integration, verification, and documentation. It may stop only at a declared stop condition, an environment/user decision blocker, or completion.
### 16.2 Worktree And Ownership Rules
- Initialize this workspace as a Git repository in Wave 0 while preserving `FilesConvertedToGitServerConcept`.
- Use one isolated branch/worktree per code-writing subagent when tasks can run in parallel.
- Never assign two active agents overlapping production paths.
- Shared files are owned only by the current foundation/integration agent: `GitServer.slnx`, `Directory.*`, `global.json`, project files, `Program.cs`, host configuration, layouts, central CSS/JS entrypoints, central `DbContext`, migrations, `eng`, and `deploy`.
- Feature agents add feature-local registration methods and EF configurations. The integration agent wires them into hosts and creates one reviewed migration after the wave.
- Subagents do not revert or rewrite user/other-agent changes.
- Commits are made only when the coordinator's execution prompt explicitly authorizes them. Every integration starts from reviewed status/diff/test evidence.
- Keep the integration branch green. Do not start the next wave with known failing required tests.
### 16.3 Required Agent Prompt Contract
Every subagent prompt must state:
```text
Role and bounded objective
Prerequisite gate and exact base commit
Owned paths and forbidden shared paths
Authoritative design decisions from this plan
Required implementation, tests, docs, and evidence
No-placeholder and no-hardcoded-production-data rule
Security/resource invariants that apply
Commands to run
Expected final report: changed paths, decisions, commands/results, risks, follow-ups
Whether commits are explicitly authorized
```
An agent that discovers a needed cross-owned change must report it to the coordinator instead of editing the shared file.
### 16.4 Agent Types
| Agent | Purpose | May edit |
|---|---|---|
| Discovery | Inspect references, dependencies, platform facts, licenses | No |
| Architecture | Write contracts/ADRs/testable invariants for an assigned foundation | Assigned docs/tests only |
| Foundation implementation | Build approved core infrastructure | Explicit owned projects/folders |
| Feature implementation | Complete one vertical slice | Matching feature folders and tests |
| Integration | Wire DI/routes/UI, resolve conflicts, create migrations | Shared files for that wave |
| Test | Add/run independent tests against integrated code | Test-owned paths; production fixes return to owner |
| Security review | Attack authorization, Git/SSH parsing, XSS, paths, secrets, resource bounds | Test/report paths only unless assigned a fix |
| Performance review | Load, memory, process, SQLite, FTS, Git bounds | Test/report paths only |
| Visual review | Playwright behavior and screenshots against Files/concepts | Playwright/baseline paths only |
| Deployment review | Clean IIS/OpenSSH install, update, uninstall, ACL and artifact validation | Deployment test/report paths only |
Test, security, performance, visual, and deployment agents must be independent from the agent that implemented the feature under review.
### 16.5 Evidence
Each gate writes evidence under `artifacts/evidence/{wave}/{commit}/` and a machine-readable `evidence.json` containing:
- Commit and build version.
- OS and tool versions.
- Pinned Git/Monaco/vendor versions.
- Commands, exit codes, durations, and test counts.
- TRX/report paths and artifact hashes.
- Environment/reference-host description.
- Known accepted risks from this plan, not new waivers.
`eng/verify.ps1`, not the coordinator's prose, generates `evidence.json` directly from command execution and raw reports. The schema requires a clean commit, exact release-bundle hash where applicable, expected suite/test IDs, discovered/passed/failed/skipped counts, exit codes, and report hashes. A gate fails on zero discovered tests, missing expected test IDs, unexpected skips, dirty-tree evidence, a mismatched bundle, or a hand-edited/invalid manifest.
Tests are not silently retried. A flaky result is a failing gate until root cause is fixed or the test is deterministically redesigned.
## 17. Dependency Graph
```mermaid
flowchart TD
W0[W0 Inventory, Git init, version and license pins]
W1[W1 Platform proofs]
W2[W2 Solution, contracts, architecture tests]
W3A[W3A SQLite and identity]
W3B[W3B Git and storage foundation]
W3C[W3C Files UI and theme foundation]
W3D[W3D Worker, jobs, observability]
I3[I3 Foundation integration]
W4[W4 Walking vertical slice]
W5A[W5A Smart HTTP]
W5B[W5B LFS]
W5C[W5C SSH and hooks]
W5D[W5D Repository lifecycle and import]
I5[I5 Git data-plane integration]
W6A[W6A Repository browser]
W6B[W6B Rich previews]
W6C[W6C Monaco workspace]
W6D[W6D Search]
I6[I6 Code-experience integration]
W7A[W7A Issues]
W7B[W7B Releases]
W7C[W7C Stars, watches, forks, activity]
W7D[W7D Checks, deployments, webhooks, notifications]
W7E[W7E Organization/admin/audit]
I7[I7 Forge foundation integration]
W8[W8 Pull requests, review, merge, conflicts]
W9[W9 Unified UI, insights, API completeness]
W10[W10 Installer, update, operations, packaging]
W11[W11 Independent hardening and release acceptance]
W0 --> W1 --> W2
W2 --> W3A
W2 --> W3B
W2 --> W3C
W2 --> W3D
W3A --> I3
W3B --> I3
W3C --> I3
W3D --> I3
I3 --> W4
W4 --> W5A
W4 --> W5B
W4 --> W5C
W4 --> W5D
W5A --> I5
W5B --> I5
W5C --> I5
W5D --> I5
I5 --> W6A
I5 --> W6B
I5 --> W6C
I5 --> W6D
W6A --> I6
W6B --> I6
W6C --> I6
W6D --> I6
I6 --> W7A
I6 --> W7B
I6 --> W7C
I6 --> W7D
I6 --> W7E
W7A --> I7
W7B --> I7
W7C --> I7
W7D --> I7
W7E --> I7
I7 --> W8 --> W9 --> W10 --> W11
```
## 18. Wave Plan
### W0 - Inventory, Repository, Versions, And Provenance
Must run sequentially before any code-writing agent. Under the 2026-08-23 amendment, the inventory, scope, version, provenance, and proposed numeric-boundary outputs remain prerequisites; unavailable reference-host measurements and final host approval are deferred release evidence rather than implementation-progression blockers.
Agents:
- One discovery agent inventories Files source/assets/tests and records the selective port map.
- One dependency agent resolves current official .NET 10 SDK/runtime, newest stable x64 Git for Windows, Git LFS test client, Monaco, Playwright, and vendor versions with official URLs and hashes.
- One license agent builds the initial provenance/notice matrix for Files assets, npm vendors, Monaco themes, Git, and all shipped binaries.
- One independent performance agent freezes the exact reference-host, deterministic dataset/load mix, resource caps, cleanup deadlines, and measurement method.
- Coordinator initializes Git and creates the baseline.
Outputs:
- `docs/scope/feature-matrix.md` with every concept capability marked included or excluded.
- `docs/architecture/reference-port-map.md` mapping Files source to planned GottaGit destination.
- `docs/scope/files-port-manifest.json` containing source hashes, exact expected application theme IDs/assets, Monaco theme IDs, and every Files preview-module concept. Each entry is `required` or has an explicit user-approved exclusion and reason; runtime enumeration is never its own completeness authority.
- `docs/security/trust-boundaries.md`.
- `docs/architecture/authority-and-consistency.md`.
- `docs/performance/reference-host.json` with every required numeric resource cap and a deterministic dataset/load manifest.
- `eng/versions.json` with exact verified pins; no floating versions.
- Third-party inventory and SBOM inputs.
Gate W0:
- Concept directory is unchanged and tracked.
- Every shipped dependency has a source, version, license/provenance, and update owner.
- The hash-addressed Files port manifest accounts for every source application theme and preview concept; exclusions have user approval.
- No production code has been copied wholesale from Files.
- The coordinator can explain every included/excluded concept item.
- By user direction on 2026-08-23, the existing W0 implementation inputs are accepted for progression while the reference-host manifest remains `proposed-blocked`; this is not W0 host approval, and all deferred host/dataset/load evidence remains mandatory before release.
### W1 - Platform Proofs
Run W1 checkpoint proof agents in parallel; all checkpoint proofs must finish before W2. Under the 2026-08-23 amendment, explicitly deferred target-host proofs finish at the later gates assigned in `docs/architecture/w1-deferred-validation.md` rather than silently counting as W1 successes.
| Proof agent | Must demonstrate on target Windows x64 |
|---|---|
| Git HTTP | Pinned Git smart HTTP protocol v2 streams through ASP.NET Core/IIS without whole-pack buffering; receive-pack and upload-pack work |
| Git formats | Create, inspect, clone, fetch, push, diff, archive, verify, and maintain SHA-1 and SHA-256 bare repositories |
| LFS | Current Git LFS client interoperates with a minimal bounded test Batch API and locking contract |
| SQLite | EF Core SQLite, WAL, FTS5, migrations, busy handling, web+worker process contention, and integrity checks work on local NTFS |
| OpenSSH | Inbox Windows OpenSSH forced key command invokes a prototype bridge; shell/PTY/forwarding/SFTP fail |
| IIS/processes | Self-contained `win-x64` ASP.NET Core works behind ANCM; cancellation kills native process trees; five-admitted-RPC-root cross-process limiter, separately capped descendants, and cross-process maintenance gate work |
| Storage admission | HTTP/SSH pushes and non-Git writes reserve bounded disk before launch, enforce native input ceilings, abort/clean quarantine before crossing reserve, and cannot overbook concurrently |
| UI/vendor | Monaco and representative preview modules run locally under planned CSP and Chromium desktop/mobile without CDN access |
Proofs may be throwaway, but executable tests and conclusions are retained. Do not build feature code around a failed assumption.
Gate W1:
- The exact smart HTTP adapter is selected and documented. The current revision passes pinned-Git protocol-v2 clone/fetch/push through Kestrel; a predecessor revision passed the retained Windows-client IIS profile, so no IIS result is claimed for the current revision until it is redeployed.
- Retained executable workstation proofs pass for both Git object formats, Git LFS, SQLite/FTS/contention, bounded storage admission, native-process coordination, and browser/vendor loading.
- Every target-host, OpenSSH, lifecycle, mixed-transport, resource, or security assumption not proved in W1 is named in `docs/architecture/w1-deferred-validation.md`, carries no positive evidence claim, and is assigned to a later gate before release.
- Any failed assumption that changes the product design still requires a user-approved design change.
- By user direction on 2026-08-23, this revised checkpoint is accepted for progression to W2. The original target Windows/IIS/OpenSSH proof matrix remains a release-risk register rather than a W2 prerequisite.
### W2 - Solution And Frozen Foundation Contracts
One foundation agent owns shared files. Other agents may write architecture tests/docs in non-overlapping paths.
Create:
- `GitServer.slnx`, projects, central package management, locked restore, analyzers, nullable, warnings-as-errors, deterministic builds, source-link/build metadata, and local tool manifest.
- Project-reference and namespace architecture tests.
- Core IDs, Git object format/OID, owner/repository slug, ref, permission, actor, lifecycle, job, content-store, clock, and result/error contracts.
- `IRepositoryAuthorization`, `IGitCommandRunner`, `IGitRepositoryStore`, `IBranchPolicy`, `IContentStore`, `IStorageAdmission`, `IMaintenanceGate`, `IHostInstanceLease`, `IApprovedHookRunner`, `IBackgroundJobQueue`, `IGitEventInbox`, and `ISearchProjection` interfaces.
- Test fixture builders that generate random users/repos/refs/OIDs rather than reusing concept values.
- `docs/scope/authorization-matrix.md` defining public/internal/private semantics and every role/capability outcome.
- `docs/scope/pat-scope-matrix.md` mapping every PAT scope to Git/LFS/REST actions and underlying capability.
- `docs/scope/api-capability-matrix.md` listing every required in-scope REST action independently of generated OpenAPI.
- Signing-key ownership/trust/revocation contracts and displayed verification states.
- Feature event contracts for notifications, activity, audit, search projection, checks, and Git ref changes so later feature agents publish events without editing shared consumers.
Gate W2:
- Clean locked restore/build/test succeeds with zero warnings.
- Dependency rules are executable, not only documented.
- Authorization, PAT, REST capability, signing trust, feature-event, theme, and preview manifests are frozen and machine-readable where applicable.
- Both object formats have unit/property tests.
- No feature UI or route exists yet.
### W3 - Parallel Foundations
All four agents start from Gate W2 and own disjoint feature paths.
W3A SQLite and identity:
- EF Core model, baseline migration, Identity, organizations/teams/grants, pending setup recovery, local-user activation, TOTP, OIDC link contract, PAT/SSH/signing-key records, audit base, optimistic concurrency.
- Real file-backed SQLite tests including 32 simultaneous first-setup claims.
W3B Git and storage:
- Pinned Git resolver/health check, command runner, opaque repository store, content store, path/reparse defenses, process limits, object/ref primitives, per-repository leases, and the sole cross-process storage-admission/reservation service used by later writers.
W3C UI foundation:
- Selectively port/rename Files shell, tokens, every application theme/theme asset required by the frozen W0 manifest, import map, dialogs, grid/list component, responsive/touch/keyboard primitives, Monaco loader, and preview module interfaces.
- No repository sample cards or concept data.
W3D worker and operations:
- Durable queue/leases, Worker host, at-most-once delivery/`OutcomeUnknown` policy, Git event spool, correlation/telemetry, health/readiness primitives, and the sole production cross-process maintenance-gate/host-instance-lease implementations used by all composition roots; fake SMTP/webhook test endpoints.
Integration I3:
- Coordinator reviews all diffs, wires DI/configuration, creates one baseline migration, and resolves only shared composition.
- Independent architecture, database, security-foundation, and UI-shell agents test the integrated result.
Gate I3:
- Build/tests pass after IIS and Worker restart.
- Exactly one public setup claimant wins under concurrency.
- Interrupted winning-admin setup can resume, and local recovery works only before an administrator finishes activation.
- Local activation credentials are one-use/expiring and normal login is impossible before activation.
- Plaintext deployment appsettings template contains no real secret and ACL tests exist.
- Every Files-derived asset appears in provenance inventory.
- Worker claims/reclaims a durable test job across forced process termination.
- A second Web host fails readiness, and exclusive maintenance prevents new Web, Worker, SshBridge, HookBridge, and Admin mutations before W4 starts.
### W4 - Walking Vertical Slice
Run sequentially because every later slice depends on it.
Implement one complete path:
1. First visitor creates administrator.
2. Administrator creates one organization and one repository.
3. Worker provisions a real bare repository with optional README seed.
4. Administrator creates a scoped PAT.
5. Current pinned Git client clones over HTTPS, commits, and pushes.
6. GottaGit repository page reads the real default branch, commit, tree, blob, and README.
7. A second user receives read permission and can browse/clone but cannot push.
8. Restart IIS and Worker; state and access remain correct.
The UI may expose only this completed path at this gate. Do not add tabs for later features.
Gate W4:
- Browser, REST, and Git use the same authorization result.
- `git fsck --strict` passes.
- Pack bodies and blobs above the configured bounded inline-view threshold stream with backpressure; small README/preview blobs may materialize only within that threshold. Memory tests enforce the configured per-request and process deltas.
- Failure during provisioning recovers to a real Failed/Ready state without an accessible orphan.
- Playwright desktop/mobile proves the real path and no dead control.
### W5 - Git Data Plane
Run four implementation agents in parallel after W4.
| Agent | Owned slice | Independent evidence |
|---|---|---|
| W5A Smart HTTP | Protocol v2, fetch/push/tag/ref operations, streaming, PAT/anonymous auth, overload, receive-service integration | Real current Git transcripts, cancellation, malformed protocol tests |
| W5B LFS | Batch transfer, locks, hash/size, associations, cleanup, disk guard | Real Git LFS clone/push/pull/lock tests and interruption tests |
| W5C SSH/hooks | Sole owner of key sync, `GitServer.SshBridge`, `GitServer.HookBridge`, central pre/post-receive handling, constrained administrator-hook runner, command parsers, and host configuration | Real SSH Git tests plus shell/forwarding and approved-hook process attack matrices |
| W5D lifecycle/import | Create/seeds, rename, transfer, delete/restore/purge, one-time HTTPS/SSH import, reconcile | Crash injection at every state transition and import SSRF/credential tests |
Integration I5:
- Wire routes, jobs, hooks, shared limiter, lifecycle locks, and migration.
- Run an authorization matrix across HTTP, SSH, LFS, public/private/internal, current/revoked PAT/key, and each role.
- Run process/recycle and Git-ref reconciliation tests.
Gate I5:
- SHA-1 and SHA-256 repositories clone/fetch/push over HTTPS and SSH.
- Current Git LFS transfer/lock flows pass.
- Five total RPCs run; the sixth waits or fails with a controlled overload result and starts no Git process.
- Simultaneous HTTP/SSH pushes, LFS, import, and maintenance cannot overbook disk; a reserve breach cancels/cleans quarantine/temp data while reads remain available.
- Protected refs cannot be bypassed by either transport.
- Revoked PAT/SSH key stops working on the next operation.
- Expired PATs fail on the next REST, Git HTTP, and LFS operation.
- No arbitrary shell/SSH command, path, process, or Git option is reachable.
### W6 - Code Experience
Run four agents after I5.
W6A repository browser:
- Dashboard grid/list, repository overview, refs, paged tree, blob, history, commits, blame, diffs, README, clone URLs, ZIP/tar.gz archives, language/contributor Git metrics.
W6B previews/themes:
- `IBlobViewerModule` implementations for every safe ported viewer concept, lazy thumbnails, immutable OID caching, module limits, sandboxed active content, every application theme.
W6C Monaco workspace:
- Multi-file read/edit draft, source-control panel, diff review, direct commit/new branch, expected-OID ref update, no-execution boundary. Persist a neutral draft-to-branch contract, but expose no create-PR or conflict control until W8 owns and wires it.
W6D search:
- Repository/code FTS ingestion, worker updates/rebuild, queries/snippets/pagination, permission filtering, stale-index revocation, skipped-file reporting.
Integration I6:
- Wire repository navigation only for completed pages.
- Run stored-XSS corpus through names, commits, refs, files, README/Markdown/raw HTML/SVG, snippets, diffs, and Monaco.
- Run Files-to-GottaGit visual review at desktop/mobile across every theme.
Gate I6:
- Grid/list show the same real Git state and persist preference.
- No tree operation extracts a working copy.
- Active content remains in an opaque sandbox under direct and iframe navigation.
- Workspace detects a moved branch and does not overwrite it.
- Revoked search access leaks no result/snippet/count/facet/autocomplete.
- Preview limits produce accurate metadata/download behavior rather than fake previews.
### W7 - Parallel Forge Foundations
Run five agents after I6.
| Agent | Complete vertical slice |
|---|---|
| W7A Issues | Issues, comments, labels, milestones, assignees, mentions, reactions, attachments, templates; publishes frozen feature events; owns issue FTS projection/query |
| W7B Releases | Tags, draft/prerelease, notes/generated notes, assets/checksums, publish/download/delete |
| W7C Social/repository network | Stars, watches, forks, upstream sync, cross-fork authorization; sole owner of global/repository activity projection/UI |
| W7D Integrations | Sole owner of notification handlers/inbox/SMTP/webhook delivery plus status/check suites/runs/annotations and deployment records; consumes frozen feature events |
| W7E Organization/admin | User/org/team/settings UI, grants, storage/free-space, hook allowlist, jobs, audit, health, retention |
Integration I7:
- Wire shared timeline, Markdown sandbox, frozen notification/activity/audit event contracts, issue search, navigation, REST contracts, and one reviewed migration. Feature producers do not edit W7C/W7D consumers.
- Test every mutation with anonymous/user/role/admin matrix and concurrent edits.
Gate I7:
- Every visible count and status changes from a persisted real mutation after reload.
- Webhook receiver sees one signed attempt for completed success/timeout/500 cases. Timeout/reset after transmission and forced process loss after attempt start persist `OutcomeUnknown` and never send again; an explicit 500 persists `FailedFinal`.
- SMTP receiver sees at most one attempt. Disconnect/timeout after `DATA` without confirmed acceptance persists `OutcomeUnknown`; explicit rejection persists `FailedFinal`; neither removes the in-app notification.
- Fork visibility and permissions cannot broaden source private/internal content.
- Retention and purge release storage without deleting shared LFS content.
### W8 - Pull Requests, Review, Merge, And Conflicts
Run after checks, forks, workspace, issues, and notifications are integrated.
One primary PR agent owns implementation. Separate Git-review and authorization-test agents work read-only or in test-only paths.
Implement:
- Create/edit/close/reopen/draft PRs across branches and permitted forks.
- Conversation, commits, files, checks, reviewers, assignees, labels, milestone, related issues.
- Unified/split bounded diffs, file filtering, line comments, threads, suggestions, review decisions.
- CODEOWNERS, required approvals/checks, stale-review behavior, signatures, branch rules.
- Merge, squash, rebase, stale-target detection, and accurate merge result.
- Three-way Monaco conflict workspace with resolution commit to source branch.
- Pull-request FTS projection/query, update/delete behavior, current-ACL filtering, and cross-type search contract.
Gate W8:
- Every write path invokes the same branch policy.
- Target/source movement during review, conflict resolution, and merge fails safely and can be retried from current refs.
- Review comments remain anchored or honestly reported outdated after force-push.
- Oversized/binary diffs show accurate fallback actions.
- A successful merge records the actual target ref/OID and cannot be duplicated by repeat request.
- Pull requests enter/update/leave search correctly, and stale private PR index rows cannot leak after permission changes.
- Playwright covers approve, request changes, comment, resolve, failed check, successful merge, and denied merge.
### W9 - Unified Product UI, Insights, And API Completeness
Must run after all feature slices exist.
Agents:
- UI integration agent aligns all routes with Files components and concept information architecture.
- Insights agent computes only confirmed Git metrics.
- API agent closes current REST/OpenAPI coverage.
- Visual agent independently tests every core page/theme/viewport.
- No-placeholder agent audits runtime routes, controls, data provenance, and static source.
Required outcomes:
- Global navigation: repositories, starred, activity, issues, pull requests, CI/CD/checks, admin, settings, and storage are present only when backed by implemented features.
- Repository navigation labels are consistent across pages.
- Packages and other exclusions are absent.
- Charts use real computed time-series and show honest empty/stale/failure states.
- Every enabled control has a success, validation, authorization, empty, and failure path.
- Current OpenAPI and a generated-client smoke test cover all public REST endpoints.
- Cross-type search covers repository/code/issue/PR manifests, deletion and visibility changes, current authorization, totals/snippets/autocomplete, and rebuild.
Gate W9:
- No concept/demo identity, repository, hash, count, timestamp, or chart remains.
- Static scan finds no production `coming soon`, `NotImplementedException`, dead `href="#"`, unconditional success, or unapproved TODO in shipped paths.
- The dynamic-field provenance manifest maps every displayed dynamic field to an authority and test ID; randomized representative mutations prove each field class updates after reload.
- Chromium desktop/mobile has no uncaught page errors, failed first-party request, overflow that blocks use, or dead action.
- Runtime themes and viewer modules exactly match the frozen external W0 port manifest, and core screenshot baselines pass for every required application theme.
### W10 - Deployment, Upgrade, And Release Packaging
Run after the integrated application is feature complete.
Agents:
- Installer agent is the sole owner of `deploy` and all install/update/uninstall script behavior.
- Operations agent owns `GitServer.Admin`, readiness/configuration implementation, and operations/backup documentation, but does not edit `deploy`.
- Release agent owns SBOM, notices, checksums, manifests, self-contained outputs.
- Deployment test agent independently exercises clean VMs.
Release bundle:
- Self-contained `win-x64` Web, Worker, SshBridge, HookBridge, and Admin outputs.
- Pinned extracted x64 Git for Windows and central hook bridge.
- Idempotent install/update/uninstall PowerShell.
- Safe configuration templates.
- Third-party notices, required bundled-source/source-offer materials, SBOM, version manifest, and SHA-256 checksums.
- Install, security, update, API-breaking-change, and repository-only backup documentation.
Gate W10:
- Clean install, repair, update with persistent real data, and uninstall pass on clean supported Windows/IIS snapshots.
- Installer changes no unrelated IIS/OpenSSH site/account/configuration.
- Final IIS endpoint passes browser, HTTPS Git, LFS, and SSH smoke tests.
- Production appsettings is preserved and not web-served; ACLs prevent unauthorized read/write.
- Self-contained applications use bundled runtime and bundled Git only; ANCM prerequisite is correctly validated.
- SBOM/notices cover every shipped file and dependency.
### W11 - Independent Hardening And Release Acceptance
No feature work begins here. Independent agents attack the same release candidate bits.
| Reviewer | Required suite |
|---|---|
| Functional | Full unit, integration, Git, LFS, SSH, REST, Worker, Playwright suites |
| Security | Authorization matrix, CSRF, XSS/sandbox, traversal, command/ref injection, SSRF import/webhook, secret redaction, rate/overload, dependency scan |
| Performance | 100 repos, 25 users, five mixed Git RPCs, 2 GB repository, 10,000-entry tree, FTS load, p95 page gate, memory/process bounds |
| Fault | Kill Web/Worker/Git/HookBridge during create/import/push/LFS/index/merge; kill approved-hook children before/after ref update; SQLite busy/corruption, disk reserve, SMTP/webhook failure, OpenSSH outage |
| Visual | Chromium desktop/mobile, every theme, core workflows and screenshot baselines |
| Deployment | Clean IIS install/update/uninstall, app-pool recycle, server reboot, migration, repository-only restore/import |
| Scope | Included feature traceability and excluded-route/navigation scan |
Gate W11:
- All required tests pass against the exact release bundle.
- No critical/high unresolved authorization bypass, command injection, path escape, stored XSS escape, secret leak, SSH escape, stale-ACL leak, or SQLite corruption issue exists.
- Load stays within the explicit envelope, metadata p95 is below one second, and every frozen process/queue/memory/output/WAL/temp/log/spool cap and cleanup deadline passes.
- Every accepted risk is documented exactly, not silently "fixed" by a fake control or broadened into a new risk.
- Final evidence manifest is complete and hash-verifiable.
## 19. Verification Strategy
### 19.1 Test Projects
| Project | Scope |
|---|---|
| ArchitectureTests | Project/reference boundaries, direct process/filesystem/DbContext/controller restrictions, feature ownership |
| UnitTests | Domain/application invariants, permission matrices, state machines, parsers, path/ref/OID properties, Markdown/viewer decisions |
| IntegrationTests | Real SQLite files, migrations, Identity, controllers/REST, jobs, storage, FTS, SMTP/webhook receivers, crash recovery |
| GitTests | Real bundled Git repositories and clients over smart HTTP, LFS, SSH, hooks, SHA-1/SHA-256, signatures, import, process bounds |
| PlaywrightTests | Chromium desktop/mobile workflows, themes, visual baselines, console/network errors, sandbox escape tests |
| DeploymentTests | Pester/PowerShell clean IIS/OpenSSH install, update, uninstall, ACLs, services, configuration, release manifest |
Use mocks only at narrow fault-injection boundaries. Git behavior tests use real temporary bare repositories and the pinned executable. SQLite tests use real local files, not EF in-memory.
### 19.2 Baseline Commands
The exact scripts are created in W2 and must be runnable from the root without undocumented setup:
```powershell
dotnet tool restore
dotnet restore .\GitServer.slnx --locked-mode
dotnet build .\GitServer.slnx -c Release --no-restore -warnaserror
dotnet test .\GitServer.slnx -c Release --no-build
pwsh .\eng\verify.ps1 -Configuration Release
pwsh .\eng\package.ps1 -Configuration Release -Runtime win-x64
```
Additional gate commands include:
```powershell
git --version
git lfs version
ssh -V
git fsck --strict
git lfs fsck
sshd.exe -t
dotnet publish -c Release -r win-x64 --self-contained true
```
The test harness must isolate Git system/global configuration and disable prompts/credential helpers.
### 19.3 Required Security Corpus
Fuzz/property/integration tests cover:
- Owner/repository slugs, refs, object IDs, Git paths, URL encoding, encoded slash/backslash, Unicode normalization, control characters, and Windows device/ADS/traversal forms.
- SSH original commands, quotes, extra tokens, shell metacharacters, alternate executables, long input, environment injection, PTY/subsystem/forwarding.
- Git service name/options, protocol headers, pkt input, malformed request lengths, cancellation, large stderr, and child-process hangs.
- Markdown/raw HTML/SVG, filenames, commit authors/messages, comments, diffs, snippets, links, media, CSP and iframe breakout payloads.
- SQLite contention, interrupted writes/migrations, stale concurrency tokens, FTS malformed input, stale ACL index, corruption/read-only/disk reserve.
- PAT/SSH revocation, role changes during requests, deleted/transferred repository races, public-to-private transitions, session security-stamp changes.
- Import and webhook URL schemes, DNS rebinding, loopback/link-local/private targets according to administrator allowlist, credential leakage, changed SSH host key.
### 19.4 No-Placeholder Gate
Use three independent controls:
1. Static scan shipped source/output for `NotImplementedException`, `coming soon`, demo/concept values, dead links/actions, unconditional success patterns, and unapproved TODO/TBD markers.
2. Runtime data-provenance tests seed randomized names/OIDs/counts/timestamps, mutate through Git/API/UI, reload, and prove displayed values track authority.
3. Route/action inventory maps every visible enabled control to an authorization rule, real endpoint/use case, persistence/Git effect, failure behavior, and end-to-end test.
Legitimate input placeholder attributes and CSS design constants are allowed. Hardcoded production records, metrics, charts, identities, hashes, or statuses are not.
### 19.5 Playwright And Visual Gate
- Chromium desktop viewport: `1440x900`.
- Chromium mobile viewport: `412x915` with touch emulation.
- Compare runtime application theme IDs/assets and viewer-module IDs with the frozen hash-addressed W0 Files port manifest; production enumeration cannot define its own expected set.
- Screenshot core dashboard, repository grid/list, code/tree/blob/preview, issue, PR overview/diff/conflict, checks, release, insights, admin, settings, setup/login, empty, denied, loading, and error states where stable.
- Fail on uncaught page/console errors, failed first-party requests, blocked workflows, missing controls, unusable overflow, or screenshot drift beyond the reviewed threshold.
- Run basic keyboard/focus and automated accessibility reporting. Accessibility findings are triaged but do not alone block release under the confirmed best-effort decision.
### 19.6 Performance Gate
On the exact W0 reference host and deterministic dataset:
- Seed 100 repositories and 25 users with realistic permission distribution.
- Include one bare repository measuring 2 GiB after the documented full maintenance/GC command and one commit containing a single tree with 10,000 direct entries. Store fixture generator seed, ref/OID manifest, object counts, and resulting directory-size hash in evidence.
- Run five concurrent mixed HTTP/SSH clone/fetch/push operations plus a fixed browser/API request mix and bounded LFS/search traffic. The manifest fixes operation percentages, request payloads, cache warm-up, cold/warm cache state, think time, run duration, and zero-tolerance setup failures.
- Measure server-observed latency for dashboard grid/list, repository overview, tree page, commit list, issue list, PR list, search, and admin storage routes. Collect at least 1,000 measured requests per route after warm-up and verify each route's warm-cache p95 below one second with less than 0.1 percent unexpected errors. Report cold-cache results separately; do not mix them to improve the percentile.
- Verify a sixth Git RPC is queued/rejected without starting another process.
- Run at least 30 minutes and fail any frozen W0 cap. No more than five HTTP/SSH RPC service roots are admitted; the sixth starts no service root. Native descendants of those roots use their separate frozen process/RSS cap, the configured pending queue never exceeds its cap, and no orphan remains past the cleanup deadline.
- From the post-warm-up baseline to test end, Web/Worker RSS and handle count may not grow by more than 5 percent or show a final-ten-minute slope above 1 percent of their frozen cap. Temp files/bytes, queue depth, event spool, and WAL must return to their frozen steady-state caps within the recorded cleanup/checkpoint deadline after load stops.
- Record CPU, memory, disk, Git child count/duration, SQLite busy/checkpoint, FTS lag, request latency, and errors.
- Throughput/latency may not regress more than 15 percent from the approved baseline on the exact profile without explicit review; never mask regression by widening caps.
### 19.7 Repository-Only Restore Test
- Quiesce the source instance.
- Copy only bare repository directories as documented.
- Install a fresh instance with new identities/configuration.
- Complete first-administrator activation and create each destination user/organization owner.
- Run the documented local `GitServer.Admin repositories ingest` command with explicit fresh owner/name/private visibility for each copied repository; it acquires exclusive maintenance and validates the privileged local source path.
- Compare all refs and run `git fsck --strict`.
- Confirm forge metadata and LFS are absent and documentation says so.
- Do not label this a full backup/restore test.
## 20. Stop Conditions
The coordinator must stop the affected wave and resolve the design or implementation if:
- An untrusted browser/REST/Git/SSH/repository-controlled value reaches a shell, executable name, Git option, SQL text, filesystem repository path, or unsandboxed application HTML sink. The only source-path exception is the explicit local-administrator, maintenance-gated, canonicalized/read-only ingestion path in Section 15.3.
- Any transport, REST endpoint, raw/blob/archive/asset route, search result, count, or autocomplete bypasses current authorization.
- Search cannot suppress stale private data immediately after permission/visibility revocation.
- SQLite is placed on remote storage, multiple web workers are enabled, migrations can race, or a corruption path fails open.
- A Git/SQLite/filesystem transition can leave an unauthorized accessible repository or report rollback after refs changed.
- SSH permits arbitrary command, shell, path, PTY, forwarding, SFTP/SCP, environment, or stale revoked-key access.
- Git child processes, queues, request bodies, output, diffs, archives, previews, temp files, memory, or execution time are unbounded.
- IIS-only behavior is assumed from Kestrel tests without a real IIS gate.
- An enabled UI control, route, count, chart, or state is not backed by an authoritative implementation and end-to-end test.
- A subagent must edit a shared/other-owned path while another owner is active.
- A required independent reviewer is the same agent that wrote the implementation.
Do not waive these stop conditions with documentation, a TODO, a hidden button, a catch-all success response, or a post-release promise.
## 21. Accepted Risks
These are deliberate product decisions and must be repeated in release/security/operations documentation.
| Accepted risk | Boundary and compensating control |
|---|---|
| First visitor owns setup | Atomic single-winner claim and permanent closure prevent multiple admins, but deployment exposure can let an unintended first visitor take over |
| Single-host SQLite | Downtime and no HA are accepted; remote SQLite, web gardens, integrity failure, and authorization fail-open are not |
| Repository-only backup | Git objects/refs can be copied/imported; loss of all forge metadata, LFS, assets, secrets, and SSH identity is accepted and explicit |
| Plaintext deployment secrets | Encryption at rest is not provided; restrictive NTFS ACLs, publish preservation, no source inclusion, redaction, and no web serving are mandatory |
| No malware scanning | Authorized content may be malicious; it must not execute on server/application origin or bypass authorization/sandboxing |
| One-attempt webhook/email | Delivery may be lost or unknowable after a crash, timeout, reset, or uncertain SMTP acceptance; at most one durable attempt and administrator-visible delivered/failed/unknown state are required |
| Unstable REST API | Clients may need changes on every release; current OpenAPI and release notes must be accurate |
| Current Git client only | Older clients may fail; only the pinned current client is tested and documented |
| Unlimited owner storage | Owner caps are absent; mandatory free-space reserve, bounded writes, monitoring, and operation limits remain |
| Best-effort accessibility | Findings are recorded and basic keyboard behavior is tested, but WCAG compliance is not a release gate |
| Administrator hooks | Trusted system administrators can execute installed hook code; repository users cannot upload/modify it and process bounds apply |
| Derived-data lag | Search/counts/activity/insights may lag Git within a documented convergence window; authorization and branch policy never use stale projection state |
Every accepted risk entry in implementation documentation names an owner, review date, and measurable boundary. No agent may broaden a risk without asking the user.
## 22. Definition Of Done
Release 1 is done only when:
- Every included capability has a real backend, authorization, persistence/Git behavior, failure state, Razor/Monaco UI, REST contract where applicable, and automated vertical-slice test.
- Every excluded capability is absent from production routes, navigation, OpenAPI, and enabled controls.
- `GitServer.slnx` restores with locked dependencies and builds in Release with zero warnings.
- Unit, architecture, integration, Git, LFS, SSH, Playwright, deployment, security, fault, and performance gates pass against the same release candidate.
- Both SHA-1 and SHA-256 repository scenarios pass using the current pinned Git.
- Current permissions agree across MVC, REST, HTTP Git, SSH, LFS, search, archive, raw/preview, release assets, workspace, and PR merge.
- Branch protection cannot be bypassed by any ref-write path.
- Active repository content cannot escape its opaque sandbox into the authenticated application origin.
- No fake/hardcoded/demo/placeholder production behavior remains.
- Clean IIS installation and one-way update work with the self-contained x64 bundle, Worker, OpenSSH/SshBridge, HookBridge, SQLite migration, and bundled Git.
- The release includes checksums, SBOM, third-party notices/source obligations, configuration templates, installer, upgrade guide, security limitations, API-breaking-change notice, and repository-only backup limitations.
- Independent reviewers sign off with machine-readable evidence and no unresolved stop condition.
Only the coordinator marks the plan complete, after verifying evidence rather than relying on subagent assertions.