This commit is contained in:
160
specs/implemented/S1_School-JSON-import-export.md
Normal file
160
specs/implemented/S1_School-JSON-import-export.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# S1 — School JSON import and export
|
||||
|
||||
Status: implemented
|
||||
|
||||
## User story
|
||||
|
||||
**As** a school maintainer,
|
||||
**I want** to export and import my dance school as a JSON file,
|
||||
**so that** I can store my school configuration locally while the application does
|
||||
not offer persistent storage,
|
||||
**and so that** I retain ownership of my data.
|
||||
|
||||
## Intent
|
||||
|
||||
Export downloads a complete snapshot of one dance school to a local JSON file.
|
||||
Import restores that snapshot as a new school or replaces the corresponding
|
||||
existing school after explicit confirmation.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Exporting an existing school to a readable JSON file.
|
||||
- Importing a school that does not exist or no longer exists.
|
||||
- Replacing an existing school with the complete imported snapshot.
|
||||
- Preserving all configured school data and relationships, including:
|
||||
- School details and its persistent unique key.
|
||||
- Dancers and their details.
|
||||
- Dance groups, types, age ranges and styles.
|
||||
- Dancer memberships, including dancers belonging to multiple groups.
|
||||
- Shows, dates, day parts and any existing group assignments to day parts.
|
||||
- Coaches and any existing links between coaches and groups.
|
||||
- Full validation, an import preview, confirmation and clear error messages.
|
||||
|
||||
Preserving existing data does not add management screens for coaches or the
|
||||
ability to assign groups to show day parts.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Merging an imported snapshot with an existing school.
|
||||
- Persistent server-side storage.
|
||||
|
||||
The existing-school prompt includes a merge option, but selecting it only displays
|
||||
that merging is not yet supported. It must not change any data. Implementing merge
|
||||
behavior requires a separate specification.
|
||||
|
||||
## Identity and file format
|
||||
|
||||
- Every school has a persistent unique key that is included in exports and
|
||||
preserved through imports and subsequent exports.
|
||||
- Import identifies an existing school by that key, not by its name or a
|
||||
runtime-generated numeric ID. The key remains meaningful after a server restart.
|
||||
- A school with the same name but a different unique key is a separate school.
|
||||
- A file contains one school and all data needed to restore it without accessing
|
||||
another school or the original server state.
|
||||
- The readable, documented JSON format includes a `formatVersion` field.
|
||||
- Users may edit the JSON manually. Edited files undergo the same validation as
|
||||
files produced by the application.
|
||||
- Unknown fields and unsupported format versions are rejected explicitly; data
|
||||
must not be silently ignored.
|
||||
- Relationships in the file must be unambiguous and restored correctly. Internal
|
||||
numeric IDs need not remain identical, provided school identity and all
|
||||
relationships are preserved without collisions with other schools.
|
||||
|
||||
## Export flow
|
||||
|
||||
1. The maintainer opens an existing school's management screen.
|
||||
2. The maintainer selects the JSON export option.
|
||||
3. The application downloads a JSON file containing a consistent, complete
|
||||
snapshot of that school.
|
||||
4. Export does not change the school or any other application data.
|
||||
|
||||
## Import flow
|
||||
|
||||
1. The maintainer selects the JSON import option and chooses a local file.
|
||||
2. The application validates the entire file before changing any stored data.
|
||||
3. For a valid file, the application shows a preview containing the school name
|
||||
and the numbers of dancers, dance groups and shows.
|
||||
4. If the unique school key is unknown, the maintainer confirms adding the school
|
||||
or cancels the import.
|
||||
5. If the key already exists, the application identifies the school that would be
|
||||
replaced and offers replace, merge or cancel:
|
||||
- **Replace:** explicitly warn that the existing school is replaced completely.
|
||||
After confirmation, replace all its configured data with the snapshot.
|
||||
- **Merge:** show a message that this functionality is not yet supported and
|
||||
leave all data unchanged.
|
||||
- **Cancel:** leave all data unchanged.
|
||||
6. A confirmed import is committed as one operation. The application must not
|
||||
expose a partially imported or partially replaced school.
|
||||
7. If validation or importing fails, show **"Import niet gelukt"** together with
|
||||
the concrete cause. The user can correct the file and try again.
|
||||
|
||||
## Validation and failure behavior
|
||||
|
||||
- Validate JSON syntax, the supported file structure and format version, required
|
||||
data, field values and all relationships before applying the import.
|
||||
- Reject unknown fields and references to missing objects, including a group's
|
||||
reference to a dancer absent from the snapshot.
|
||||
- A failure must not create a partial school, partially replace an existing
|
||||
school, or modify another school.
|
||||
- A replacement must not remove the original school until the complete
|
||||
replacement can succeed. If it fails, the original school remains intact.
|
||||
- Error messages explain the cause specifically enough to correct the file.
|
||||
For example: **"Import niet gelukt: groep Hiphop verwijst naar een onbekende
|
||||
danser."**
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
### Export
|
||||
|
||||
1. Each existing school offers a JSON-file export that can be downloaded and
|
||||
stored locally.
|
||||
2. The export includes its persistent unique key, `formatVersion`, all configured
|
||||
data listed in scope and all relationships between those objects.
|
||||
3. Exporting leaves the application data unchanged.
|
||||
4. A school with no dancers, groups or shows can be exported and imported.
|
||||
|
||||
### Adding a school
|
||||
|
||||
5. A valid file with an unknown school key shows the preview before any data is
|
||||
added. Confirming creates the complete school; cancelling changes nothing.
|
||||
6. An exported school can be restored after the original school is deleted or
|
||||
the in-memory server state is lost.
|
||||
7. An existing school with the same name but a different key is neither replaced
|
||||
nor treated as the same school.
|
||||
|
||||
### Replacing a school
|
||||
|
||||
8. A valid file with an existing school key prompts the user to replace, merge or
|
||||
cancel and clearly identifies the existing school.
|
||||
9. Confirming replacement replaces the complete configuration. Objects and
|
||||
relationships present only in the previous configuration are not retained as
|
||||
part of the replaced school.
|
||||
10. Other schools remain unchanged by replacement.
|
||||
11. Selecting merge displays that merging is not yet supported and changes
|
||||
nothing. Cancelling also changes nothing.
|
||||
|
||||
### Validation and errors
|
||||
|
||||
12. Malformed JSON, unsupported format versions, unknown fields, missing required
|
||||
data, invalid field values and unresolved relationships cause the entire
|
||||
import to fail.
|
||||
13. Each failed import displays **"Import niet gelukt"** and a concrete cause.
|
||||
14. A failed new-school import adds nothing. A failed replacement preserves the
|
||||
entire existing school. Other schools are unaffected in either case.
|
||||
15. After a failure, the user can select a corrected file and retry.
|
||||
|
||||
### Round-trip integrity
|
||||
|
||||
16. Exporting and importing a school preserves every configured field and
|
||||
relationship, including a dancer's membership in multiple groups, shows and
|
||||
their day parts, and any existing coaches or day-part group assignments.
|
||||
17. Exporting the restored school again preserves its unique school key and
|
||||
equivalent configuration, even if internal numeric IDs changed.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records agreed behavior. Backend endpoints, the detailed JSON
|
||||
schema and frontend implementation remain implementation work; this review does
|
||||
not implement the feature.
|
||||
200
specs/implemented/S4_create-build-pipeline-at-gitea
Normal file
200
specs/implemented/S4_create-build-pipeline-at-gitea
Normal file
@@ -0,0 +1,200 @@
|
||||
# S4 — Build and publish pipelines in Gitea
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a maintainer, I want every branch push to build and test the application,
|
||||
so that broken changes are detected and successful main-branch builds provide
|
||||
identifiable Docker images in our own registry.
|
||||
|
||||
## Agreed environment and feasibility
|
||||
|
||||
- Gitea and its container registry run on the existing Synology.
|
||||
- The existing development mini-PC runs the Gitea Actions runner, separately from
|
||||
Gitea. No additional hardware is available or required.
|
||||
- Gitea supports push-triggered Actions workflows and a runner on a separate
|
||||
machine. Codex can implement the repository configuration and assist with the
|
||||
installation and configuration required on the existing machines.
|
||||
- Gitea was inspected as version 1.25.4. Match the runner and workflow setup to
|
||||
the installed version rather than assuming newer documentation applies.
|
||||
- The mini-PC was inspected as Linux x86_64 with a Docker client installed, but
|
||||
without a reachable Docker daemon. Configuring a working daemon is part of S4.
|
||||
- The current internal Gitea/registry endpoint is `http://192.168.2.28:3000`.
|
||||
Use that endpoint over the trusted internal network and explicitly configure
|
||||
Docker clients that need registry access to trust this particular HTTP registry.
|
||||
Introducing HTTPS is outside S4.
|
||||
- The runner and job containers need access to Gitea, the registry and dependency
|
||||
download sources. The runner connects to Gitea; it needs no public incoming port.
|
||||
- The mini-PC must be on, awake and running the runner. Jobs wait while it is
|
||||
unavailable; S4 does not promise unattended availability when the PC is off.
|
||||
|
||||
References:
|
||||
|
||||
- [Gitea 1.25 Actions quickstart](https://docs.gitea.com/1.25/usage/actions/quickstart/)
|
||||
- [Gitea 1.25 Actions design](https://docs.gitea.com/1.25/usage/actions/design/)
|
||||
- [Gitea container registry](https://docs.gitea.com/usage/packages/container/)
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Version-controlled Gitea Actions workflows and supporting build configuration.
|
||||
- Enable Actions as needed at instance and repository level, configure Docker on
|
||||
the mini-PC, and install, register and configure its runner.
|
||||
- Build and test both backend and frontend for every push to every branch,
|
||||
including newly created branches, except when the author intentionally uses a
|
||||
supported skip marker such as `[skip ci]`. Separate tag and pull-request event workflows
|
||||
are not required; branch pushes also check changes used in pull requests.
|
||||
- Build two runnable Docker images: backend and frontend.
|
||||
- Run end-to-end tests against those built containers before publication.
|
||||
- Publish both images only from successful builds of the `main` branch to the
|
||||
container registry on the Synology.
|
||||
- Configure registry authentication and the necessary secrets outside Git.
|
||||
- Preserve failure diagnostics and document operation and recovery.
|
||||
- Demonstrate a real successful pipeline and images that can be pulled back.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Automatic deployment, starting application containers on the Synology, and OTAP.
|
||||
Starting temporary containers for pipeline tests is in scope.
|
||||
- New linting or static-analysis gates, such as ESLint or Sonar. Existing tests,
|
||||
including architecture tests, remain mandatory.
|
||||
- Merge or release policies, separate tag/release workflows, and automatic image
|
||||
deletion or retention cleanup. Published images remain available for now.
|
||||
- Multi-architecture images, HTTPS setup, new hardware or provisioning additional
|
||||
infrastructure.
|
||||
|
||||
## Build and verification behavior
|
||||
|
||||
1. Every ordinary branch push runs backend and frontend builds and their existing
|
||||
tests. Explicit Gitea-supported skip markers are an accepted maintainer-approved
|
||||
opt-out.
|
||||
2. Backend verification includes the existing unit, integration/system and
|
||||
architecture tests. Current entry point: `mvn clean verify` using Java 25.
|
||||
3. Frontend verification uses the lockfile (`npm ci`), unit tests (`npm test`) and
|
||||
production build (`npm run build`) with a supported Node version.
|
||||
4. Build both Docker images on every branch, including branches that cannot
|
||||
publish. The current Dockerfile only covers the backend; frontend packaging
|
||||
must be added as part of implementation.
|
||||
5. The frontend image serves the production Angular build, supports direct SPA
|
||||
route navigation, and forwards `/api` requests to the backend container.
|
||||
Container addressing/configuration is an implementation choice.
|
||||
6. Run the existing Playwright end-to-end suite with Chromium against the built
|
||||
frontend/backend containers, through the frontend's API forwarding. Adapt the
|
||||
existing development-server test configuration as necessary: the acceptance
|
||||
run must exercise the actual images, not development servers.
|
||||
7. Determine the intended server's CPU architecture during implementation. Build
|
||||
for that single target architecture and run the end-to-end tests on that same
|
||||
architecture. Do not infer the Synology's architecture from the mini-PC.
|
||||
Any architecture mismatch must be resolved and tested on the existing hardware
|
||||
before claiming acceptance.
|
||||
8. A failed build or test fails the pipeline and prevents publication. Test
|
||||
containers are temporary and are cleaned up after the run, including failure.
|
||||
|
||||
## Publication and image identity
|
||||
|
||||
- Publish separate backend and frontend images under the repository owner's
|
||||
namespace in the existing Gitea container registry. Document the exact names.
|
||||
- Feature branches must not publish application images.
|
||||
- Both images from a main-branch commit use the full Git commit SHA as their tag.
|
||||
This identifies the matching pair independently of moving tags.
|
||||
- Once both commit images have been successfully published, reruns verify/reuse
|
||||
them without overwriting either commit tag.
|
||||
- Publication succeeds only when both images are published and can be pulled
|
||||
back from the registry. A partial publication fails the pipeline; one image may
|
||||
already exist. A rerun preserves that image and may publish the missing image.
|
||||
- After both commit images are available, update the moving `main` tags only if
|
||||
the commit is still the current main-branch head. Serialize/coordinate that
|
||||
operation so an older, slower pipeline cannot move `main` backwards.
|
||||
- The two moving tags are not an atomic pair. Use the same commit SHA on both
|
||||
images when an exact matching pair is needed. A failure updating a moving tag
|
||||
must be visible as a pipeline failure and recoverable through a rerun.
|
||||
- No automatic deletion of published images is introduced in S4.
|
||||
|
||||
## Failure diagnostics and operation
|
||||
|
||||
- Failed pipelines retain available test reports, container logs, and Playwright
|
||||
traces and screenshots for fourteen days. Collect available diagnostics even
|
||||
when a preceding step fails; do not hide the original failure.
|
||||
- Provide a short management guide covering:
|
||||
- Docker/runner installation, registration, startup and required access.
|
||||
- Gitea instance/repository Actions settings and registry configuration.
|
||||
- Required credentials, permissions and secret names, without secret values.
|
||||
- Which settings exist outside Git and how to reproduce them.
|
||||
- Trigger behavior, mini-PC availability and queued jobs.
|
||||
- Image names, tags and commands to pull a matching image pair.
|
||||
- Finding diagnostics, rerunning failed jobs and completing partial publication.
|
||||
- The target architecture and how it was established.
|
||||
- Keep registry credentials and registration tokens out of repository files and
|
||||
logs; use the relevant secret settings.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] A push to any branch, including a new branch, starts a pipeline, except for
|
||||
an explicit supported skip marker chosen by the author.
|
||||
- [x] Backend and frontend build and all existing tests, including architecture
|
||||
and Playwright end-to-end tests, pass before publication is permitted.
|
||||
- [x] Every branch builds both Docker images; end-to-end tests exercise those
|
||||
images through the frontend and its `/api` forwarding.
|
||||
- [x] A failing build or test fails the pipeline without publishing images.
|
||||
- [x] A successful feature-branch pipeline publishes no application images.
|
||||
- [x] A successful `main` pipeline publishes both images to the Synology registry
|
||||
with the full commit SHA; both images can be pulled back.
|
||||
- [x] Published commit images are preserved on rerun; partial publication can be
|
||||
completed without overwriting an existing commit image.
|
||||
- [x] Moving `main` tags are updated only after both commit images are available,
|
||||
and an older pipeline cannot move them backwards.
|
||||
- [x] Publication or pull-verification failure makes the pipeline fail, even if
|
||||
some images have already been uploaded.
|
||||
- [x] Available failure diagnostics are retained for fourteen days, and temporary
|
||||
test containers are cleaned up on success and failure.
|
||||
- [x] The runner operates on the existing mini-PC, with Gitea and the registry on
|
||||
the existing Synology; no additional hardware is needed.
|
||||
- [x] The single target architecture is established and the images are tested on
|
||||
that architecture using the existing hardware.
|
||||
- [x] A management guide records setup, external settings, secrets, image usage
|
||||
and recovery, including the need to keep the mini-PC/runner available.
|
||||
- [x] Actual pipeline runs demonstrate successful main-branch publication,
|
||||
feature-branch checks without publication, and failure blocking publication.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification captures the agreed design. It does not install the runner,
|
||||
change server settings or implement the pipeline. S4 is complete only when the
|
||||
configuration, documentation and operational acceptance evidence are delivered;
|
||||
workflow files alone are insufficient.
|
||||
|
||||
|
||||
## Implementation progress
|
||||
|
||||
Repository implementation and local Docker verification are available. See
|
||||
[management instructions](../../docs/gitea-ci.md) and
|
||||
[validation evidence](../../docs/s4-validation.md).
|
||||
|
||||
Backend verification (20 tests), frontend verification (14 tests), both runtime
|
||||
image builds and both Playwright tests against the containers passed. Fifteen
|
||||
Java CI publication/configuration tests pass. The runner binary and user-service
|
||||
configuration are installed on the mini-PC.
|
||||
|
||||
The maintainer confirmed the Synology as `x86_64` / `linux/amd64`. Gitea secrets
|
||||
and the target-platform variable are configured; the runner is registered and
|
||||
online. Registry login succeeded. Real feature runs #1 and #3 passed, including
|
||||
container E2E; deliberate failure run #2 blocked the build/publication path and
|
||||
provided downloadable diagnostics.
|
||||
|
||||
PR #1 was subsequently merged by the maintainer. Main run #7 succeeded for
|
||||
commit `2356a31aa612c8b0ce4b386a0a65da6589e23285`, publishing and pulling both
|
||||
full-SHA images and both main aliases. Registry digests are recorded in the
|
||||
validation evidence.
|
||||
|
||||
The final real-registry probes confirmed partial-publication recovery, immutable
|
||||
commit-tag preservation on rerun and stale-main protection in isolated validation
|
||||
repositories. Application manifests remained unchanged. The maintainer confirmed
|
||||
that the Synology app.ini has no actions section, so Gitea 1.25.4's documented
|
||||
90-day artifact and 365-day log defaults apply; the workflow requests fourteen
|
||||
days for diagnostic artifacts. Explicit skip markers are accepted by the
|
||||
maintainer. All acceptance criteria are met; see the validation evidence for
|
||||
probe details, digests and the distinction from full Gitea workflow reruns.
|
||||
Reference in New Issue
Block a user