From 424f14f4f5577bb47fea41c8f3a655dca953e6d8 Mon Sep 17 00:00:00 2001 From: Jens Tirsvad Nielsen Date: Mon, 5 Oct 2026 12:28:58 +0800 Subject: [PATCH] Plan RepoFoundry: business case, stakeholders, plan, milestones, UC-001 Add the planning baseline for RepoFoundry (create-project.sh), which creates GitHub and Gitea repositories, a Gitea -> GitHub push mirror and a local project with the SQA-QC-Framework. - BC-001 Business Case and SA-001 Stakeholder Analysis (S01, S02, S03) - PP-001 Project Plan: three phases, 2026-10-05 to 2026-11-13 (proposed) - MIL-001 Foundation, MIL-002 Repositories and Mirror, MIL-003 Scaffold and Release, with 18 task rows - US-001, UC-001 "Create a new project" and SSD-001 - Registry: PO language en; PP, MIL, US, UC and SSD rows added Decisions recorded: origin uses HTTPS from GITEA_URL unless the SSH test on port 10022 passes; S01 and S02 are held by one person for now. Refs: no issues synced yet (sync-project.sh dry run only) --- .gitmodules | 3 + AGENTS.md | 53 +++++++ docs/artifact-registry.md | 46 ++++++ docs/business-case.md | 135 ++++++++++++++++++ docs/milestones/mil-001-foundation.md | 74 ++++++++++ .../mil-002-repositories-and-mirror.md | 76 ++++++++++ .../mil-003-scaffold-and-release.md | 77 ++++++++++ docs/project-plan.md | 91 ++++++++++++ docs/stakeholder-analysis.md | 73 ++++++++++ docs/uc-001/ssd.md | 50 +++++++ docs/uc-001/uc.md | 83 +++++++++++ docs/user-stories.md | 49 +++++++ framework | 1 + 13 files changed, 811 insertions(+) create mode 100644 .gitmodules create mode 100644 AGENTS.md create mode 100644 docs/artifact-registry.md create mode 100644 docs/business-case.md create mode 100644 docs/milestones/mil-001-foundation.md create mode 100644 docs/milestones/mil-002-repositories-and-mirror.md create mode 100644 docs/milestones/mil-003-scaffold-and-release.md create mode 100644 docs/project-plan.md create mode 100644 docs/stakeholder-analysis.md create mode 100644 docs/uc-001/ssd.md create mode 100644 docs/uc-001/uc.md create mode 100644 docs/user-stories.md create mode 160000 framework diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a759dc9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "framework"] + path = framework + url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..aaa1f03 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,53 @@ +# AGENTS.md + +This project uses the SQA and QC framework mounted at `framework/`. + +For any document under `docs/` (create, edit or review) use the `artifact` +skill. For planning a project or a phase into tasks, and syncing phases and +tasks to Gitea/GitHub as Milestones and Issues, use the `project-planning` +skill. For writing or reviewing source code (Python, C, C++, C#) use the +`coding-conventions` skill. Skills are read from `.agents/skills/` (this harness and Codex CLI) +and `.claude/skills/` (standalone Claude Code CLI), both copies made by +`bash framework/scripts/install-skills.sh` — re-run it after updating the +framework. + +**Never commit, push or open a PR unless asked.** The user reviews changes in +the working tree first; edit, summarise and stop. The commit/PR rules below +apply once a commit has been asked for. + +## Workflow order + +Business Case, Stakeholder Analysis, Project Plan, milestones, tasks synced as +issues, then code. Nothing goes under `src/` or `tests/` unless a milestone +document (`MIL-*`) is accepted and the task is a row in it (ideally a synced +issue). If those are missing, plan with the `project-planning` skill, show the +dry-run output of `bash framework/scripts/sync-project.sh`, and stop. The rule +is defined once in `framework/process/plan-first-gate.md`. + +A "build X" request is planning-first: produce the plan and issues, then ask +for a go-ahead. Only the user can waive the plan, in chat, for that request. +Before planning, find the Product Owner's language (the prompt, or the +`Languages` section of `docs/artifact-registry.md`); if neither states it, ask. + +To enforce the gate at commit time, run +`bash framework/scripts/install-git-hooks.sh --enable-plan-gate`: a commit that +changes `src/` or `tests/` then needs a `Task: MIL-NNN#N` trailer. + +Rules that apply to every document: + +1. Get the short name from `framework/registry/artifact-catalog.md` and the + next version from `docs/artifact-registry.md`. Create files with + `bash framework/scripts/new-artifact.sh `. +2. Owners, reviewers and RACI use stakeholder IDs from the project's + Stakeholder Analysis, never invented role names. +3. Every QC criterion is tagged with an ISO/IEC 25010:2023 characteristic. +4. Every reviewed instance gets an `RC-*` record in `docs/sqa/reviews/`. +5. Do not edit `framework/` from this project; propose changes upstream. +6. Every PR description closes the issues its work completes, one + `Closes #N` per line (`Refs #N` for partial work); see the + `project-planning` skill. +7. Every document's `## Version History` has `Change` and `Commit` columns and + keeps the two latest rows. After committing, run + `framework/scripts/resolve-pending-commits.sh` and commit the result before + opening the PR (no amend). Never ask for or perform the merge: a reviewer + merges. diff --git a/docs/artifact-registry.md b/docs/artifact-registry.md new file mode 100644 index 0000000..ddc4ff7 --- /dev/null +++ b/docs/artifact-registry.md @@ -0,0 +1,46 @@ +# Artifact Registry + +This project's artifact state. Types, short names and `CrossReference +Candidates` come from the framework catalog +(`framework/registry/artifact-catalog.md`); this file only records where +each document lives in *this* project and the next version to use. + +Delete rows for types you don't use. Add a row the first time you create a +document of a type. `Primary File` may contain a glob (e.g. +`docs/uc-*/uc.md`); `framework/scripts/find-crossreferences.sh` reads it. + +| Short Name | Artifact Type | Primary File | Next Available Version | +| --- | --- | --- | --- | +| BC | Business Case | docs/business-case.md | 002 | +| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 | +| PP | Project Plan | docs/project-plan.md | 002 | +| MIL | Milestone / Gateway | docs/milestones/*.md | 004 | +| US | User Story | docs/user-stories.md | 002 | +| UC | Use Case | docs/uc-*/uc.md | 002 | +| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 002 | + +## Languages + +Set the PO language when the project starts; `project-planning` asks for it +if it is missing. A translated artifact is named `..md` +(for example `business-case.da.md`); the English file stays the source. + +| Setting | Value | +| --- | --- | +| PO language | en | +| High-level register | IT Executive English | +| Technical register | IT Professional English | + +| Artifact types | Register | Also kept as a PO-language file | +| --- | --- | --- | +| BC, KPI, PP, MIL | IT Executive English | Yes | +| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | Yes | +| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No | + +## Notes + +- "Next Available Version" is the zero-padded (3-digit) version to use the + *next* time a new document of that type is created. Increment it only when + a brand-new document is created, not when an existing document's + `## Version History` gets a row. +- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types. diff --git a/docs/business-case.md b/docs/business-case.md new file mode 100644 index 0000000..b2ec394 --- /dev/null +++ b/docs/business-case.md @@ -0,0 +1,135 @@ +# Business Case + +## Metadata +| Key | Value | +| --- | --- | +| ID | BC-001 | +| CrossReference | [SA-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Executive Summary + +Starting a new project at TirSystem currently means several manual, error-prone steps across two git hosts: create a repository on GitHub, create a matching one on the self-hosted Gitea instance, wire a push mirror between them, then set up a local clone with the SQA-QC-Framework. RepoFoundry is a single Bash script (`create-project.sh`) that performs these steps from prompts and two small configuration files, handles credentials without ever exposing them, and reports exactly what succeeded when a step fails. + +## Methodological and Standards Foundation + +The project follows the SQA and QC framework mounted at `framework/` (plan-first gate, artifact catalog, QC checklists). Quality criteria are tagged with ISO/IEC 25010:2023 characteristics; security is the primary one (confidentiality of tokens), followed by reliability (partial-failure recovery) and maintainability. Code follows the framework's `coding-conventions` skill for Shell. + +## Problem Statement + +- Repository setup is repeated by hand for every new project and is easy to get subtly wrong (wrong owner, mirror in the wrong direction, tokens left in remote URLs). +- A half-finished setup (one host created, the other not) leaves no record of what exists. +- The framework submodule, skills, hooks and templates are installed inconsistently between projects. + +## Business Opportunity + +One repeatable, reviewed procedure gives every new project the same secure baseline: Gitea as the source of truth, GitHub as a mirror, and the SQA-QC-Framework in place from the first commit. + +## Objectives + +1. Create an empty GitHub repository under a chosen user or organization. +2. Create a matching empty Gitea repository under a chosen user or organization. +3. Configure the Gitea repository as a push mirror to GitHub (direction Gitea to GitHub). +4. Create the local project directory with `origin` (Gitea) and `github` remotes that contain no credentials. +5. Add the SQA-QC-Framework as the `framework` submodule, install its skills and git hooks, and copy its templates, optionally enabling the plan gate. +6. Never print or persist a token, and never overwrite existing files or directories without consent. + +## Scope + +### In Scope + +- `create-project.sh`, `config.env.example`, `.env.example`, `.gitignore` and `README.md`. +- Safe parsing and validation of `config.env` and `.env` (never `source`d). +- Prompts for name, description, visibility and owner on both hosts. +- Checks for required tools (`git`, `curl`, optional `jq`) before any change. +- A check that the project name is not already taken on GitHub. +- Partial-failure reporting with a documented way to continue. +- Documentation of the SSH prerequisite for the submodule (Gitea SSH on port `10022`). + +### Out of Scope + +- Deleting or rolling back repositories (no destructive commands; cleanup is manual and documented). +- Managing repositories after creation (branch protection, webhooks, teams, CI). +- Hosts other than GitHub and the configured Gitea instance. +- Creating or rotating tokens and SSH keys. +- Making the first commit or opening a pull request. + +## Expected Benefits + +### Tangible Benefits + +- Setup of a new project drops from several manual steps to one command. +- Every project starts with the same remotes, mirror direction and framework installation. + +### Intangible Benefits + +- Lower risk of credential leaks. +- A documented, reviewable setup procedure that GitHub readers can reuse. + +## Strategic Alignment + +Supports developing on self-hosted Gitea while publishing to GitHub, and adopting the SQA-QC-Framework as the standard process for new projects. + +## Success Criteria + +| # | Criterion | Target | Measure | +| --- | --- | --- | --- | +| 1 | Credential exposure | 0 occurrences of a token in output, saved remote URLs, config files or leftover temp files | Test run with log review; `git config --get-regexp remote` inspected | +| 2 | Repository ownership | Both repositories are created under the owner chosen at the prompt, never silently under `GITHUB_USER` | Test run with a user owner and with an organization owner | +| 3 | Mirror direction | Gitea is the source, GitHub the target; a push to `origin` appears on GitHub | Push a test commit and compare | +| 4 | Partial failure | When one host fails, the output lists what was created and the command to continue | Forced failure test (invalid token for one host) | +| 5 | No overwrite | An existing directory or file is never replaced without a yes | Run twice in the same location | +| 6 | Lint | `shellcheck` reports no errors on `create-project.sh` | `shellcheck create-project.sh` | + +## Risks + +| Risk | Impact | Mitigation | +| --- | --- | --- | +| Gitea ignores `sync_on_commit` when a push mirror is created through the API (known upstream issue) | Mirror only syncs on its interval | Set an interval, trigger a first sync through the API and report the effective setting | +| GitHub PAT lacks permission to create repositories or to push | Creation or mirroring fails | Document the required scopes; check with a read-only API call first and stop with a clear message | +| Gitea stores the mirror credentials server-side | A Gitea admin could access the GitHub token | Document it; recommend a fine-grained PAT limited to the one repository where possible | +| SSH to Gitea port `10022` is not configured | Submodule add fails after repositories already exist | Check SSH reachability before creating anything; document the prerequisite | +| Framework hook installer changes `core.hooksPath` | An existing hook setup is silently replaced | Inspect the current value first and ask for consent | +| Repository name conflicts on a host | Creation fails midway | Check availability on both hosts before creating either | + +## Assumptions + +- The Gitea instance exposes the v1 REST API including `push_mirrors` (confirmed on version 1.27.3 at `https://git.tirsystem.com`). +- The user has working SSH access to `git.tirsystem.com` on port `10022`. +- The GitHub PAT may be used both for API calls and as the push-mirror credential. + +## Constraints + +- Bash only, with `git` and `curl` required and `jq` optional. +- `config.env` and `.env` are parsed, never `source`d. +- No `rm -rf`, and no token in any URL, log or remote. +- The framework under `framework/` is not edited from this project. + +## Cost–Benefit Assessment + +| Costs | Benefits | +| --- | --- | +| Three planned phases of maintainer time; ongoing maintenance when the GitHub or Gitea API changes | Repeatable secure setup for every future project; fewer setup mistakes; reusable by GitHub readers | + +## Stakeholders + +| Stakeholder ID (SA) | Interest in this project | +| --- | --- | +| S01 | Product Owner and maintainer; sets scope and accepts the result | +| S02 | DevOps, cybersecurity and maintainer; reviews credential handling and git host integration | +| S03 | Reads and may reuse the published project on GitHub | + +## Recommendation + +Proceed — the procedure is small, well bounded and removes a repeated, security-sensitive manual task. + +--- + +[SA-001]: ./stakeholder-analysis.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/milestones/mil-001-foundation.md b/docs/milestones/mil-001-foundation.md new file mode 100644 index 0000000..6747e0a --- /dev/null +++ b/docs/milestones/mil-001-foundation.md @@ -0,0 +1,74 @@ +# MIL-001 Foundation + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-001 | +| CrossReference | [BC-001], [US-001], [UC-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose + +Decide whether the secure base of `create-project.sh` is sound enough to build the host integration on: configuration, credential handling, logging, prompts and tests. + +## Deliverable + +`create-project.sh` skeleton that parses `config.env` and `.env` safely, validates input, prompts for the repository details and makes no network or filesystem change yet, together with `config.env.example`, `.env.example`, `.gitignore` and a test harness. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | `shellcheck create-project.sh` reports no errors | Clean | Any error | +| 2 | Neither config file is `source`d; unknown keys and malformed lines are rejected | Tests pass | Any accepted | +| 3 | No token appears in stdout, stderr or a log in any test, including failure paths | None found | Any found | +| 4 | Missing `git` or `curl` stops the script before any change | Stops with a clear message | Continues | +| 5 | `.env` is ignored by git; both example files contain placeholders only | Verified | Real value present | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| None | First phase | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objective 6 (no credential exposure, no overwrite) | [BC-001] | +| Success criteria 1 and 6 | [BC-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S02 | + +## Target Date + +2026-10-16 — proposed; the Business Case sets no deadline. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Define project name and configuration files | Keep the working name RepoFoundry in one constant so it is easy to change, and confirm on GitHub that the name is free (the exact name returned 404 on 2026-10-05; only `RepoFoundryAI` by another owner exists). Create `config.env.example` with `GITHUB_API_URL=https://api.github.com`, `GITHUB_WEB_URL=https://github.com`, `GITEA_URL=https://git.tirsystem.com/` and a Gitea API base (`GITEA_API_URL`, default `https://git.tirsystem.com/api/v1`; the request listed `GITEA_URL` twice, the second is treated as the API URL). Create `.env.example` with empty `GITHUB_PAT`, `GITHUB_USER`, `GITEA_TOKEN`. | No | | +| 2 | Script skeleton with strict mode and safe helpers | `set -Eeuo pipefail`, an ERR/EXIT trap, `mktemp` with `umask 077` and cleanup on exit, small single-purpose functions, logging helpers that redact known secret values, and no `rm -rf`. Follow the framework `coding-conventions` Shell rules. | No | | +| 3 | Safe parser for config.env and .env | Read `KEY=VALUE` lines without `source` or `eval`; accept only whitelisted keys, strip optional quotes, reject control characters, and validate that service URLs are well-formed `https` and that credentials are non-empty. Warn when `.env` is readable by other users. | No | | +| 4 | Tool check and HTTP helper | Check `git` and `curl` (and optional `jq`, with a fallback parser for the few JSON fields needed) before any change. Wrap `curl` so tokens go through a private curl config file or stdin rather than the command line (visible in process lists), with `--fail-with-body` handling, timeouts, and error messages that carry the HTTP status but never the credential. | No | | +| 5 | Interactive prompts and input validation | Prompt for repository name, description, visibility and the owner or organization separately for GitHub and Gitea, with defaults taken from configuration. Validate names against both hosts' allowed characters. `GITHUB_USER` is only the authenticating account and is never assumed to be the owner. | Yes | [UC-001] | +| 6 | .gitignore and test harness | Add `.env` and temporary files to `.gitignore`. Add a test harness with stubbed `curl` and `git` that covers parser rejection cases and the no-token-in-output check, run alongside `shellcheck`. | No | | + +--- + +[BC-001]: ../business-case.md +[US-001]: ../user-stories.md +[UC-001]: ../uc-001/uc.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/milestones/mil-002-repositories-and-mirror.md b/docs/milestones/mil-002-repositories-and-mirror.md new file mode 100644 index 0000000..a29f637 --- /dev/null +++ b/docs/milestones/mil-002-repositories-and-mirror.md @@ -0,0 +1,76 @@ +# MIL-002 Repositories and Mirror + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-002 | +| CrossReference | [BC-001], [US-001], [UC-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose + +Decide whether the script creates both remote repositories under the correct owners and configures the Gitea to GitHub push mirror reliably, including when something fails halfway. + +## Deliverable + +`create-project.sh` creating an empty GitHub repository and an empty Gitea repository, configuring the push mirror, verifying it, and printing a summary of what exists, with documented token permissions. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | Repositories are created under the owner chosen at the prompt, for a user owner and for an organization owner, on both hosts | Both verified | Any under the wrong owner | +| 2 | Both repositories are empty (no README, licence or `.gitignore` generated by the host) | Verified | Any commit present | +| 3 | A commit pushed to Gitea appears on GitHub; nothing flows the other way | Verified | Wrong direction or no sync | +| 4 | Mirror credentials are never part of a remote URL, log or output | None found | Any found | +| 5 | With an invalid token on one host, the script stops before creating anything or reports exactly what was created and how to continue | Verified | Silent or misleading | +| 6 | Required token scopes and the `sync_on_commit` limitation are documented | Present in README draft | Missing | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| [MIL-001] | Needs the parser, HTTP helper and prompts | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objectives 1, 2 and 3 | [BC-001] | +| Success criteria 2, 3 and 4 | [BC-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S02 | +| Approving reviewer | S01 | + +## Target Date + +2026-10-30 — proposed. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Preflight checks before any creation | With read-only calls, verify both tokens (`GET /user` on each host), that the owner exists and the token may create repositories there, and that the name is free on both hosts, so one host is not created and the other refused. Also test SSH to `git.tirsystem.com` on port 10022 (needed for the submodule); its result decides whether `origin` later uses SSH (test passed) or HTTPS (default). | Yes | [UC-001] | +| 2 | Create the empty GitHub repository | `POST /user/repos` when the owner is the authenticated user, otherwise `POST /orgs/{org}/repos`, with `auto_init` false. Use the visibility from the prompt. Report the HTTP status and a hint on failure, without exposing the token. | Yes | [UC-001] | +| 3 | Create the empty Gitea repository | `POST /user/repos` or `POST /orgs/{org}/repos` on the Gitea API base, with `auto_init` false and no template, readme, licence or gitignore. Derive the clone URL from `GITEA_URL` and the selected owner. | Yes | [UC-001] | +| 4 | Configure the Gitea to GitHub push mirror | Call `POST /repos/{owner}/{repo}/push_mirrors` with `remote_address` (the GitHub HTTPS URL built from `GITHUB_WEB_URL` and the GitHub owner, without credentials), `remote_username` (`GITHUB_USER`), `remote_password` (`GITHUB_PAT`), an interval and `sync_on_commit`. Gitea has a known issue where `sync_on_commit` can be ignored on API creation, so read the result back, trigger `push_mirrors-sync`, and report the effective setting. The PAT needs push access to the target repository (classic `repo` scope, or a fine-grained token with Contents write). Stop with a clear error if it is missing. Confirm the mirror feature is enabled on the Gitea server. | Yes | [UC-001] | +| 5 | Partial-failure reporting and resume | Track each step (GitHub repo, Gitea repo, mirror) in a state summary. When a step fails, print what succeeded, what did not, and the exact way to continue. When rerun and the repository already exists and is empty, offer to reuse it instead of failing. Never delete anything automatically. | No | | +| 6 | Document token permissions and API limitations | Draft the README sections on required GitHub PAT permissions (create in user or org, push), Gitea token scopes (repository write, organization write for org repos), the fact that Gitea stores the mirror password server-side, and the `sync_on_commit` limitation. | No | | + +--- + +[BC-001]: ../business-case.md +[US-001]: ../user-stories.md +[UC-001]: ../uc-001/uc.md +[MIL-001]: ./mil-001-foundation.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/milestones/mil-003-scaffold-and-release.md b/docs/milestones/mil-003-scaffold-and-release.md new file mode 100644 index 0000000..ac018d9 --- /dev/null +++ b/docs/milestones/mil-003-scaffold-and-release.md @@ -0,0 +1,77 @@ +# MIL-003 Scaffold and Release + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-003 | +| CrossReference | [BC-001], [US-001], [UC-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose + +Decide whether the project is ready to release: the local project is scaffolded with the framework, the documentation is complete and an end-to-end review found no credential, ownership or mirror-direction defect. + +## Deliverable + +Complete `create-project.sh` (local directory, credential-free remotes, framework submodule, skills, hooks, templates, optional plan gate), `README.md`, and a written final review with the list of external prerequisites. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | `git remote -v` shows `origin` (Gitea) and `github` with no credentials in either URL | Verified | Any credential | +| 2 | `framework` is a submodule at the configured URL and the install scripts have run once, in the documented order | Verified | Missing or repeated | +| 3 | An existing directory, `AGENTS.md` or `docs/artifact-registry.md` is never overwritten without a yes | Verified by a second run | Overwritten | +| 4 | With the plan gate enabled, a commit touching `src/` or `tests/` without a `Task: MIL-NNN#N` trailer is refused | Verified | Accepted | +| 5 | An existing `core.hooksPath` is reported and not replaced without consent | Verified | Replaced silently | +| 6 | README covers installation, configuration, usage examples, security decisions, error handling and stakeholders, in clear English | Reviewed by S02 | Section missing | +| 7 | End-to-end run on disposable repositories passes and the final review records no open security finding | Recorded in an `RC-*` | Open finding | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| [MIL-002] | Needs the remote repositories and the mirror | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objectives 4, 5 and 6 | [BC-001] | +| Success criteria 1, 5 and 6 | [BC-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S02 | + +## Target Date + +2026-11-13 — proposed. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Create the local project directory and credential-free remotes | After consent, create the directory (refuse to reuse an existing one without a yes), run `git init` on `main`, and add `origin` (Gitea) and `github` using URLs derived from the configured base URLs and the selected owners, with no token in any URL. `origin` uses HTTPS derived from `GITEA_URL`, unless the SSH test from the preflight passed, in which case it uses SSH on port 10022. Do not make a commit. | Yes | [UC-001] | +| 2 | Add the framework submodule | From the project directory run `git submodule add ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git framework`. Check beforehand that SSH on port 10022 works and stop with an actionable message if not. Document that this SSH access must be configured. | Yes | [UC-001] | +| 3 | Install skills and git hooks, with optional plan gate | Run `framework/scripts/install-skills.sh` and `install-git-hooks.sh`. The hook installer only sets `core.hooksPath` to `framework/githooks` and is safe to rerun, but it would replace a different existing value, so read the current value first and ask. Offer `--enable-plan-gate` as an optional choice, which requires a `Task: MIL-NNN#N` trailer on commits changing `src/` or `tests/`. | Yes | [UC-001] | +| 4 | Copy the framework templates without overwriting | Copy `AGENTS-template.md` to `AGENTS.md` and `artifact-registry-template.md` to `docs/artifact-registry.md` after `mkdir -p docs`, asking before replacing an existing file. | Yes | [UC-001] | +| 5 | Write README.md | Clear English for GitHub readers: installation, configuration (`config.env`, `.env`), usage examples, security decisions, error handling and partial-failure recovery, the SSH prerequisite for port 10022, token permissions, and the stakeholders: Tirsvad (Product Owner and maintainer, https://www.linkedin.com/in/tirsvad74), Michael Kragh (DevOps, cybersecurity and maintainer, https://www.linkedin.com/in/codemikemike/) and GitHub readers. | No | | +| 6 | End-to-end test and final security review | Run the whole flow against disposable repositories for a user owner and an organization owner. Review credential handling, repository ownership, mirror direction, submodule setup and API limitations, record the result in an `RC-*` review, and summarise the files created and the external prerequisites. | No | | + +--- + +[BC-001]: ../business-case.md +[US-001]: ../user-stories.md +[UC-001]: ../uc-001/uc.md +[MIL-002]: ./mil-002-repositories-and-mirror.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/project-plan.md b/docs/project-plan.md new file mode 100644 index 0000000..cfa468c --- /dev/null +++ b/docs/project-plan.md @@ -0,0 +1,91 @@ +# Project Plan + +## Metadata +| Key | Value | +| --- | --- | +| ID | PP-001 | +| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [US-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose + +Schedule the three phases that deliver RepoFoundry (`create-project.sh` and its documentation) in dependency order. The Business Case sets no deadline, so the dates below are proposals for S01 to confirm. + +## Planning Assumptions + +- Week 1 starts 2026-10-05; the plan ends by 2026-11-13. +- Phase length: two weeks. +- S01 and S02 review each phase through a pull request, as described in [SA-001]. For now one person holds both roles. +- The PO language is English, so no translated copies are kept. + +## Gateway Schedule + +| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone | +| --- | --- | --- | --- | --- | --- | --- | --- | +| Foundation | [MIL-001] | 2026-10-05 to 2026-10-16 | 2026-10-16 | S01 | US-001.01 | Safe skeleton, config parsing, prompts, tests | | +| Repositories and Mirror | [MIL-002] | 2026-10-19 to 2026-10-30 | 2026-10-30 | S02 | US-001.01 | GitHub and Gitea repositories and the push mirror | | +| Scaffold and Release | [MIL-003] | 2026-11-02 to 2026-11-13 | 2026-11-13 | S01 | US-001.01 | Local project, framework, README, final review | | + +```plantuml +@startgantt +Project starts 2026-10-05 +[Foundation] starts 2026-10-05 and ends 2026-10-16 +[Foundation Go/No-Go] happens 2026-10-16 +[Repositories and Mirror] starts 2026-10-19 and ends 2026-10-30 +[Repositories and Mirror Go/No-Go] happens 2026-10-30 +[Scaffold and Release] starts 2026-11-02 and ends 2026-11-13 +[Scaffold and Release Go/No-Go] happens 2026-11-13 +@endgantt +``` + +## Scope Coverage + +| Business Case scope item | Gateway | +| --- | --- | +| Safe parsing of `config.env` and `.env`, tool checks, prompts, `.gitignore` | [MIL-001] | +| Project name check on GitHub | [MIL-001] | +| Creation of both repositories and the push mirror | [MIL-002] | +| Partial-failure reporting | [MIL-002] | +| Local directory, remotes, framework submodule, skills, hooks, templates, plan gate | [MIL-003] | +| README and SSH prerequisite documentation | [MIL-003] | + +## Dependencies + +``` +MIL-001 → MIL-002 → MIL-003 +``` + +A No-Go moves every later date by the time needed to rework the failed criteria. + +## Plan Risks + +| Risk | Impact | Mitigation | +| --- | --- | --- | +| No disposable GitHub organization for testing | Organization-owner path untested | Agree the test owners before [MIL-002] starts | +| Gitea API behaviour differs from the swagger on the live server | Mirror task takes longer | Test against `git.tirsystem.com` early in [MIL-002] | + +## Open Issues + +- Confirm the proposed dates (S01). +- Decided: `origin` uses HTTPS derived from `GITEA_URL`, unless the SSH test passed, in which case it uses SSH on port 10022. +- Decided: use case [UC-001] "Create a new project" is created, with [SSD-001]; tasks that implement its steps reference it. +- Decided: S01 and S02 are both held by one person for now. +- Open: this plan says the script does not make the first commit; confirm. + +--- + +[BC-001]: ./business-case.md +[SA-001]: ./stakeholder-analysis.md +[MIL-001]: ./milestones/mil-001-foundation.md +[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md +[MIL-003]: ./milestones/mil-003-scaffold-and-release.md +[US-001]: ./user-stories.md +[UC-001]: ./uc-001/uc.md +[SSD-001]: ./uc-001/ssd.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/stakeholder-analysis.md b/docs/stakeholder-analysis.md new file mode 100644 index 0000000..77f4901 --- /dev/null +++ b/docs/stakeholder-analysis.md @@ -0,0 +1,73 @@ +# Stakeholder Analysis + +## Metadata +| Key | Value | +| --- | --- | +| ID | SA-001 | +| CrossReference | [BC-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose + +Identify who is affected by RepoFoundry and what each needs from it, so owners and reviewers in later artifacts can cite stable IDs. Method: power/interest grid. + +## Stakeholder Summary Table + +| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) | +| --- | --- | --- | --- | --- | --- | --- | --- | +| S01 | Tirsvad | Product Owner and maintainer | Not stated | HIGH | HIGH | Manage Closely | New projects start from one repeatable, correct setup | +| S02 | Michael Kragh | DevOps, cybersecurity and maintainer | Not stated | HIGH | HIGH | Manage Closely | Credentials are never exposed and the git host integration is safe | +| S03 | GitHub readers | Readers of the published project | Not stated | LOW | MEDIUM | Keep Informed | Clear documentation they can follow and reuse | + +## Power/Interest Classification Rationale + +- **Manage Closely (S01, S02):** the two maintainers decide scope, accept the result and own the code. For now one person holds both roles, so one person both authors and reviews; this should be revisited when a second person takes S02. +- **Keep Informed (S03):** readers cannot change the project but depend on its README being accurate. + +## Primary Concerns and FURPS+ Mapping + +| ID | Concern | FURPS+ attribute | +| --- | --- | --- | +| S01 | One command creates both repositories, the mirror and the project | Functionality | +| S02 | No token in output, URLs or files; no silent overwrite | Functionality (security) | +| S02 | A failed step leaves a clear record of what exists | Reliability | +| S03 | Installation, configuration and usage are documented in clear English | Usability | + +## Communication Requirements + +| ID | Channel | Frequency | Deliverable | Phase / Milestone | +| --- | --- | --- | --- | --- | +| S01 | Pull request review | Per phase | Accepted milestone document | MIL-001, MIL-002, MIL-003 | +| S02 | Pull request review | Per phase | Security review of the changes | MIL-002, MIL-003 | +| S03 | README on GitHub | At release | README.md | MIL-003 | + +## Conflicting Interests and Mitigations + +| Conflict | Stakeholders | Mitigation | +| --- | --- | --- | +| Convenience of one-step setup against strict consent prompts for every overwrite | S01, S02 | Prompt only where something would be changed; offer `--yes` only for non-destructive steps (to be decided in MIL-001) | + +## Traceability Analysis + +### Business Goal Alignment + +| Stakeholder | Concern | Business Case objective | +| --- | --- | --- | +| S01 | One-command setup | [BC-001] objectives 1–5 | +| S02 | Credential safety, no overwrite | [BC-001] objective 6 | +| S03 | Reusable documentation | [BC-001] objective 6 and the README deliverable | + +## Sign-Off + +Pending review by S02. + +--- + +[BC-001]: ./business-case.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/uc-001/ssd.md b/docs/uc-001/ssd.md new file mode 100644 index 0000000..bad3ab7 --- /dev/null +++ b/docs/uc-001/ssd.md @@ -0,0 +1,50 @@ +# System Sequence Diagram + +## Metadata +| Key | Value | +| --- | --- | +| ID | SSD-001 | +| CrossReference | [UC-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Source Use Case + +Create a new project ([UC-001]) — scenario: main success scenario + +## Diagram + +```plantuml +@startuml +actor Maintainer as A +participant ":System" as S +A -> S : startProjectCreation() +S --> A : prompts for project details +A -> S : provideProjectDetails(name, description, visibility, githubOwner, giteaOwner, directory, enablePlanGate) +S --> A : checks passed +S --> A : creation summary +@enduml +``` + +## System Operations + +| Step | Message | Parameters | Return | Use case step | +| --- | --- | --- | --- | --- | +| 1 | startProjectCreation | none | prompts for project details (after configuration and tool checks) | 1, 2 | +| 2 | provideProjectDetails | name, description, visibility, githubOwner, giteaOwner, directory, enablePlanGate | checks passed, then a creation summary | 3 to 10 | + +Steps 4 to 9 are internal to the system, so one operation covers them. A consent question (step 8a, 9a, 9b) is a prompt from the system and is out of scope for this diagram; failure flows are out of scope here. + +## Lifecycle Notes + +The system is one script run. It starts with the first operation and ends after the summary; nothing persists between runs. + +--- + +[UC-001]: ./uc.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/uc-001/uc.md b/docs/uc-001/uc.md new file mode 100644 index 0000000..f039024 --- /dev/null +++ b/docs/uc-001/uc.md @@ -0,0 +1,83 @@ +# Create a new project + +## Metadata +| Key | Value | +| --- | --- | +| ID | UC-001 | +| CrossReference | [US-001], [SA-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +**Format:** Fully Dressed + +## Fully Dressed + +- **Scope:** RepoFoundry (`create-project.sh`) +- **Level:** user-goal +- **Primary Actor:** Maintainer (S01 or S02; one person holds both roles for now) +- **Stakeholders and Interests:** + - S01 — new projects start from one repeatable, correct setup + - S02 — credentials are never exposed and nothing is overwritten silently + - S03 — the published procedure is documented and reusable +- **Preconditions:** + - `config.env` and `.env` exist and are valid. + - `git` and `curl` are installed. + - The Maintainer has a GitHub PAT, a Gitea token and SSH access to Gitea on port 10022. +- **Postconditions (success guarantee):** + - An empty repository exists on GitHub and on Gitea under the chosen owners. + - The Gitea repository is a push mirror to GitHub. + - A local project directory exists with credential-free remotes `origin` (Gitea) and `github`, the `framework` submodule, installed skills and hooks, and the copied templates. + - The Maintainer has a summary of what was created. + +### Main Success Scenario + +1. The Maintainer starts the project creation. +2. The system loads and validates the configuration and credentials and checks that the required tools exist. +3. The Maintainer provides the repository name, description, visibility, the GitHub owner, the Gitea owner, the local directory, and whether to enable the plan gate. +4. The system checks that both tokens work, that the owners accept new repositories, that the name is free on both hosts, and whether SSH to Gitea works. +5. The system creates the empty GitHub repository. +6. The system creates the empty Gitea repository. +7. The system configures the Gitea repository as a push mirror to GitHub and verifies it. +8. The system creates the local project with the `origin` and `github` remotes. +9. The system adds the framework submodule, installs its skills and hooks (and the plan gate if chosen) and copies the templates. +10. The system reports a summary of what was created. + +### Extensions (Alternative / Exception Flows) + +- 2a. A required tool is missing, or a configuration value is missing or malformed: + 1. The system stops before any change and names the problem without showing a credential. +- 4a. A token is invalid, an owner does not accept the repository, or the name is taken: + 1. The system stops before creating anything and says which check failed. +- 4b. SSH to Gitea does not work: + 1. The system uses HTTPS for `origin` and warns that the framework submodule step will fail until SSH is configured. +- 5a, 6a, 7a. A step fails after an earlier one succeeded: + 1. The system stops and reports what exists, what failed and how to continue. +- 8a, 9a. The target directory or a target file already exists: + 1. The system asks the Maintainer before replacing it; on no, it skips that item and reports it. +- 9b. A different `core.hooksPath` is already set: + 1. The system asks before replacing it. + +### Special Requirements / Business Rules + +| Step | Rule | +| --- | --- | +| 2, 4 | A token never appears in output, logs, command lines, remote URLs or temporary files left behind | +| 3 | The GitHub owner and the Gitea owner are chosen separately; `GITHUB_USER` is only the authenticating account | +| 7 | The mirror direction is Gitea to GitHub | +| 8 | `origin` uses HTTPS derived from `GITEA_URL`, or SSH when the SSH test in step 4 passed | +| 8, 9 | Nothing is overwritten or deleted without consent, and no commit is made | + +### Open Issues + +- The exact SSH `origin` URL form (port 10022) is settled in MIL-003. + +--- + +[US-001]: ../user-stories.md +[SA-001]: ../stakeholder-analysis.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/docs/user-stories.md b/docs/user-stories.md new file mode 100644 index 0000000..bd70432 --- /dev/null +++ b/docs/user-stories.md @@ -0,0 +1,49 @@ +# User Story + +## Metadata +| Key | Value | +| --- | --- | +| ID | US-001 | +| CrossReference | [BC-001], [MIL-001], [MIL-002], [MIL-003] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [9ae0cba] | + +--- + +## Purpose and Scope + +One epic: setting up a new project on GitHub and Gitea with the SQA-QC-Framework in place. The actor is the Maintainer (S01 or S02; for now one person holds both roles). No Use Case Diagram exists yet, so the actor name is defined here and must be reused by the use case. + +## Story List + +### US-001.01 — Create a new project + +**As a** Maintainer, **I want** to create a new project with empty GitHub and Gitea repositories, a Gitea to GitHub push mirror and a local project with the SQA-QC-Framework, **so that** every new project starts from the same secure, repeatable baseline. + +**Acceptance Criteria** + +- Given valid configuration and credentials, when the Maintainer answers the prompts, then an empty GitHub repository and an empty Gitea repository exist under the chosen owners. +- Given both repositories exist, when the mirror step finishes, then the Gitea repository is a push mirror to GitHub and no credential is stored in any remote URL. +- Given the repositories exist, when the local step finishes, then the project directory has `origin` (Gitea) and `github` remotes, the `framework` submodule, installed skills and hooks, and the copied templates. +- Given a step fails, when the script stops, then it reports what was created and how to continue. +- Given a target directory or file already exists, when the script would replace it, then it asks first. + +| Traces to | Size | INVEST exceptions | +| --- | --- | --- | +| [UC-001], [MIL-001], [MIL-002], [MIL-003] | spans three phases; delivered by the tasks of each | Small: the story is split into tasks per phase | + +## INVEST Check + +Independent, Negotiable, Valuable, Estimable and Testable hold. Small does not: this is an epic-sized story, delivered through the tasks of the three milestones, with an exception recorded above. + +--- + +[BC-001]: ./business-case.md +[UC-001]: ./uc-001/uc.md +[MIL-001]: ./milestones/mil-001-foundation.md +[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md +[MIL-003]: ./milestones/mil-003-scaffold-and-release.md +[9ae0cba]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/9ae0cba306577833480f692c67c0ec327ff2e24e diff --git a/framework b/framework new file mode 160000 index 0000000..14d221e --- /dev/null +++ b/framework @@ -0,0 +1 @@ +Subproject commit 14d221ec1cfd3966611a3eff6a607ef1964526c2