Accept planning baseline and UC-001 artifacts

Add the Use Case Diagram, Domain Model (use case and project), Dictionary,
Operation Contract, Sequence Diagram, review records RC-001 to RC-015 and
the Traceability Matrix. Split US-001 into one story per milestone, make
GitHub optional (AGPL license applied when chosen), and accept BC-001,
SA-001, PP-001, UCD-001, US-001, UC-001, SSD-001, DM-001, DM-002, OC-001,
SD-001, DICT-001 and MIL-001 to MIL-003 after review.

Refs: no issues synced yet (sync-project.sh dry run only)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 13:41:36 +08:00
co-authored by Claude Sonnet 5.5
parent fa3beaf1c1
commit 02875aee5f
32 changed files with 1666 additions and 73 deletions
+6 -3
View File
@@ -9,7 +9,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited US-001.01<br>Target date accepted | pending |
---
@@ -30,6 +31,7 @@ Decide whether the secure base of `create-project.sh` is sound enough to build t
| 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 |
| 6 | All acceptance criteria of US-001.01 in [US-001] are met | Verified | Any unmet |
## Dependencies
@@ -41,6 +43,7 @@ Decide whether the secure base of `create-project.sh` is sound enough to build t
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| User story US-001.01 | [US-001] |
| Objective 6 (no credential exposure, no overwrite) | [BC-001] |
| Success criteria 1 and 6 | [BC-001] |
@@ -53,7 +56,7 @@ Decide whether the secure base of `create-project.sh` is sound enough to build t
## Target Date
2026-10-16 — proposed; the Business Case sets no deadline.
2026-10-16 — the Business Case sets no deadline, so it does not constrain this date; accepted together with PP-001.
## Tasks
@@ -63,7 +66,7 @@ Decide whether the secure base of `create-project.sh` is sound enough to build t
| 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] |
| 5 | Interactive prompts and input validation | Prompt for repository name, description, visibility, whether to also create a GitHub repository (which also applies the AGPL license to the Gitea repository), and the owner or organization separately for Gitea and (if chosen) GitHub, 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 | |
---
@@ -9,28 +9,30 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited US-001.02<br>Purpose and criterion 1 reworded for optional GitHub<br>Target date accepted | pending |
---
## 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.
Decide whether the script creates the Gitea repository and, if GitHub is chosen, the GitHub repository 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.
`create-project.sh` creating a Gitea repository (with the AGPL license when GitHub is chosen, otherwise empty) and, if chosen, an empty GitHub 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 |
| 1 | Repositories are created under the owner chosen at the prompt, for a user owner and for an organization owner, on each host used | Both verified | Any under the wrong owner |
| 2 | The GitHub repository is created empty. The Gitea repository holds only the AGPL license file when GitHub is chosen, otherwise it is empty. Neither has a generated README or `.gitignore` | Verified | Any other commit present |
| 3 | When GitHub is chosen, a commit pushed to Gitea (including the license file) appears on GitHub; nothing flows the other way. When GitHub is not chosen, no GitHub call is made | Verified | Wrong direction, no sync, or a GitHub call without the choice |
| 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 |
| 7 | All acceptance criteria of US-001.02 in [US-001] are met | Verified | Any unmet |
## Dependencies
@@ -42,6 +44,7 @@ Decide whether the script creates both remote repositories under the correct own
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| User story US-001.02 | [US-001] |
| Objectives 1, 2 and 3 | [BC-001] |
| Success criteria 2, 3 and 4 | [BC-001] |
@@ -54,16 +57,16 @@ Decide whether the script creates both remote repositories under the correct own
## Target Date
2026-10-30 — proposed.
2026-10-30 — the Business Case sets no deadline, so it does not constrain this date; accepted together with PP-001.
## 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] |
| 1 | Preflight checks before any creation | With read-only calls, verify the tokens needed for the chosen hosts (`GET /user`; GitHub only when chosen), 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 (optional) | Only when the Maintainer chose GitHub. `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 Gitea repository, with AGPL license when GitHub is chosen | `POST /user/repos` or `POST /orgs/{org}/repos` on the Gitea API base, with no template, readme or gitignore. When GitHub is chosen, send `license` `AGPL-3.0` (listed by `GET /licenses`; check it exists first) with `auto_init` true so the license file is committed and the repository is not empty; otherwise `auto_init` false and the repository stays empty. Derive the clone URL from `GITEA_URL` and the selected owner. | Yes | [UC-001] |
| 4 | Configure the Gitea to GitHub push mirror (when GitHub is chosen) | Skip this step when GitHub was not chosen. Otherwise 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 | |
@@ -9,7 +9,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] |
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited US-001.03<br>Traces to objective 7<br>Criterion 2 names the framework URL<br>Target date accepted | pending |
---
@@ -25,13 +26,14 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor
| # | 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 |
| 1 | `git remote -v` shows `origin` (Gitea) and, when GitHub was chosen, `github`, with no credentials in any URL; with GitHub chosen the local history contains the license commit | Verified | Any credential, or a missing license commit |
| 2 | `framework` is a submodule of `ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git` 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 |
| 8 | All acceptance criteria of US-001.03 in [US-001] are met | Verified | Any unmet |
## Dependencies
@@ -43,8 +45,9 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objectives 4, 5 and 6 | [BC-001] |
| Success criteria 1, 5 and 6 | [BC-001] |
| User story US-001.03 | [US-001] |
| Objectives 4, 5, 6 and 7 | [BC-001] |
| Success criteria 1, 5, 6 and 7 | [BC-001] |
## Ownership
@@ -55,13 +58,13 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor
## Target Date
2026-11-13 — proposed.
2026-11-13 — the Business Case sets no deadline, so it does not constrain this date; accepted together with PP-001.
## 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] |
| 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, only if GitHub was chosen, `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. When the Gitea repository is not empty (GitHub chosen, AGPL license), fetch it and check out its default branch so the local history starts from the license commit. 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] |