Development Workflow Document

How a use case goes from backlog to merged: branch, issue status, testing gate, pull request.

Development Workflow Document — Heimdall API

1. Purpose

This document defines how a use case moves from backlog to merged — the branch, the issue status transitions, the testing gate, and the pull request. It is the standard every contributor (human or agent) follows so that each use case (UC-01 … UC-29 in the Use Case Specification Document , plus later additions such as UC-30) is delivered the same way.

It complements the Testing Specification Document , which defines how the tests themselves are written; this document defines when they happen in the delivery flow.

One use case = one branch = one issue = one pull request.

2. Workflow at a glance

flowchart TD
    A["Pick a use case<br/>(issue in Todo)"] --> B["Create branch from develop<br/>feature/uc-##-use-case-name"]
    B --> C["Move issue → In Progress"]
    C --> D["Implement the use case"]
    D --> E["Move issue → Testing"]
    E --> F["Write unit + functional tests"]
    F --> G["Run tests"]
    G --> H{All pass?}
    H -->|No| I["Fix code / tests"]
    I --> G
    H -->|Yes| J["Open pull request into develop"]
    J --> K["Human review"]
    K --> L{Approved?}
    L -->|Changes requested| I
    L -->|Yes| M["Human merge to develop<br/>delete feature branch"]
    M --> N["Move issue → Done and close it"]

The diagram shows the default flow, where a human reviews and merges. In an authorized batch run the agent merges its own pull request instead — every other step, including the testing gate, is identical. See Step 7.1 .

3. Issue status lifecycle

Each use case is tracked by its GitHub issue on the project board. The Status field moves through these columns, in order:

OrderStatusSet when
1TodoThe use case has not been started (default).
2In ProgressA feature branch has been created and implementation has begun.
3TestingImplementation is finished; unit and functional tests are being written, run, and fixed until green.
4DoneThe pull request has been reviewed and merged to develop; the issue is then closed.

An issue only ever moves forward during normal flow. If review requests changes, work continues on the same branch (still linked to the same issue) until tests pass again and the PR is re-reviewed.

4. Step-by-step

Step 1 — Branch from develop

Every use case is implemented on its own branch, created from an up-to-date develop — the integration branch. main only ever receives releases (see §5 ):

git switch develop
git pull
git switch -c feature/uc-01-create-scope

Branch naming pattern:

feature/uc-##-use-case-name
  • ## — the zero-padded use case number (01, 02, … 29).
  • use-case-name — the use case name in lower-case kebab-case.

A change that is not a use case — a defect, a dependency, documentation — goes on a fix/<name> or feature/<name> branch in the same way. Those two prefixes are the only ones the Branch Policy check accepts into develop (besides Dependabot’s), and it also refuses a branch that was cut from main instead of develop.

Use caseBranch
UC-01: Create Scopefeature/uc-01-create-scope
UC-11: Login (Authenticate)feature/uc-11-login
UC-25: Sign Up / Sign In via Googlefeature/uc-25-sign-up-sign-in-via-google

Step 2 — Move the issue to In Progress

As soon as the branch exists and work starts, set the use case’s issue Status to In Progress on the project board.

Step 3 — Implement the use case

Implement the use case per its specification (main flow and alternative flows) and the project’s architecture and technology stack. All commits for the use case go on its feature branch.

Step 4 — Move the issue to Testing

When the implementation is finished, set the issue Status to Testing. This signals that the feature is code-complete and the testing gate is now in progress.

Step 4.1 — If the change touches personal data

A migration that adds a column holding personal data is not finished when it compiles. Before the testing gate:

  1. State the column’s purpose in §5.1 of the Data Protection Document . PersonalDataPurposeTests fails the build if a column is missing, so this is enforced rather than remembered.
  2. Give it a retention period in the Data Retention Schedule , or say which existing row covers it. A column with no period is one kept forever, which NFR-19 forbids.
  3. Check whether it changes the record of processing — a new category of data, recipient, or transfer means the Data Protection Document needs more than a table row.

The order matters: a column that cannot be given a purpose in step 1 is a column not to add. That is what data protection by design (GDPR Art. 25, LGPD Art. 6 III) asks for, applied at the only moment it is cheap.

Step 4.2 — The periodic security review

GDPR Art. 32(1)(d) requires a process for regularly testing and evaluating the technical and organisational measures, not merely having them. That process is:

WhenWhat
Every quarterRestore a backup into a scratch environment and run the erasure reconciliation against it (Operations & Infrastructure §0.1). A restore procedure that has never been run is a hypothesis
Every quarterConfirm encryption at rest is still in force for the database volume and its backups, and that the database connection still requires TLS
Every six monthsRe-read the Threat Model against the code. A threat closed by a control that has since been refactored away is worse than one still marked open
On any change to processingRevisit the DPIA , the record of processing, and the retention schedule

The cadence matters less than the fact that each item has one. An unscheduled review is one that happens after an incident.

Step 5 — Test until green

Following the Testing Specification Document :

  1. Write the unit tests for every Command/Query handler and any new Domain behavior (main flow + each applicable AF-xx alternative flow).
  2. Write the functional tests for each endpoint (main flow + every AF-xx, including the authorization flows), end-to-end against Testcontainers PostgreSQL.
  3. Run the tests (dotnet test, and/or filtered by Category=Unit / Category=Functional).
  4. Fix any failures — in the implementation or the tests.
  5. Re-run, and repeat steps 3–4 until every test passes.

A use case does not leave the Testing stage until the full suite is green.

Step 6 — Open a pull request

With all tests passing, push the branch and open a PR from feature/uc-##-… into develop. The PR description should reference the use case and its issue (e.g. Closes #<issue-number>) so the issue is linked to the PR.

Step 7 — Human review and merge

  • The PR is reviewed by a human. Requested changes are addressed on the same branch (back to Step 5 whenever code changes, so the suite stays green).
  • Once approved, a human merges the PR into develop.
  • The feature branch is deleted after the merge.

Review and merge are human actions. An agent may prepare and push the PR, but must not self-approve or merge it. The single exception is an authorized batch run — see Step 7.1 .

Step 7.1 — Authorized batch runs

When several use cases are delivered in one unattended run, the human approval gates would stop the run at every use case, which defeats the point of batching them. For a batch run only, an agent may merge its own pull requests, subject to all of the following:

  • The batch was authorized up front. A human agreed to the specific use cases, in order, and was told explicitly that the agent would merge, close the issues, and delete the branches. A general instruction to work autonomously is not this authorization.
  • The invariant still holds. One use case = one branch = one issue = one pull request. Use cases are never batched into a shared branch or a shared pull request, so the run stays reviewable after the fact.
  • The testing gate is unchanged. The full suite is run and read for every use case, per Step 5. A merge on an unread or failing suite is never permitted.
  • No protection is bypassed. No --admin merge, no self-approval to satisfy a required review, no force-push, and no disabling or filtering of a test to make the suite green.
  • A failure stops the whole run. A red suite, a merge conflict, an ambiguous specification, or a requirement that does not exist ends the batch. Already-merged use cases stay merged; the failing branch and its pull request are left in place as evidence.

Outside an authorized batch run, Step 7 applies as written: a human reviews and a human merges.

Step 8 — Close the issue

After the merge, set the issue Status to Done and close it. If the PR used a Closes #<issue-number> reference, the merge closes the issue automatically — still confirm the board shows it in Done.

5. From develop to a release

A merged use case is on develop, not yet in production: Jenkins deploys every push to develop to the development environment, which runs on demand — a stopped one stays stopped until scripts/ygg.sh env start development on the VPS turns it on (the four environments are listed in §0.2 of the Operations & Infrastructure Document ). Releases are cut from develop as release/<major>.<minor>.<patch> branches and reach main only through a pull request that Jenkins merges itself, after deploying the release to homologation (on demand, like development) and then to production; it also tags the merge v<major>.<minor>.<patch>. Nobody merges into main by hand, and a release branch carries no commits of its own — a fix for a release lands on develop through a fix/ branch, and a new release is cut. The full procedure, including finalizing the changelog before the release branch is cut, is in CONTRIBUTING.md .

6. Definition of Done

A use case is done only when all of the following hold:

  • Implemented on a feature/uc-##-use-case-name branch created from develop.
  • Main flow and every alternative flow from the use case specification are implemented.
  • Unit tests cover each handler and new Domain behavior (main + applicable AF-xx).
  • Functional tests cover each endpoint (main + every AF-xx, including authorization).
  • The full test suite passes (Category=Unit and Category=Functional).
  • A pull request was merged to develop — reviewed by a human, or merged by an agent under an authorized batch run (Step 7.1).
  • The feature branch was deleted.
  • The issue is in Done and closed.

7. References