MIL-001 Baseline and project setup #23

Merged
Tirsvad merged 3 commits from mil-001-baseline-and-setup into main 2026-10-24 17:42:55 +02:00
19 changed files with 1210 additions and 0 deletions
Showing only changes of commit c5a6ed5985 - Show all commits
+35
View File
@@ -0,0 +1,35 @@
# Secrets and local data
.env
*.sqlite
flight_cache.sqlite*
# Python
__pycache__/
*.py[cod]
*.egg-info/
build/
dist/
.venv/
venv/
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
coverage.xml
htmlcov/
# Doxygen output
docs/doxygen/
# Editors and OS
.idea/
.vscode/
.DS_Store
Thumbs.db
# Written by pywhatkit; holds message history and phone numbers
PyWhatKit_DB.txt
# AI agent tooling installed by the framework
.agents/
.claude/
+3
View File
@@ -0,0 +1,3 @@
[submodule "framework"]
path = framework
url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git
+59
View File
@@ -0,0 +1,59 @@
# 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 | docs/milestones/mil-*.md | 006 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 008 |
## Languages
Set the PO language when the project starts; `project-planning` asks for it
if it is missing. An artifact of a type marked "Written in the PO language"
exists once, in that language, under its normal name (`business-case.md`); the
`artifact` skill ("One file per artifact") has the rule.
| Setting | Value |
| --- | --- |
| PO language | en |
| PO domain | it |
| High-level register | IT Executive English |
| Technical register | IT Professional English |
| Wiki languages | en and the PO language, at least (`framework/process/wiki.md`) |
Every artifact of a type marked "Yes" below states its language and domain in
its `Language` and `Domain` Metadata rows; `new-artifact.sh` fills them from
`PO language` and `PO domain`. `Language` is a BCP 47 code (`da`, `en`).
`Domain` is a value from this list; add a row to introduce a domain, so a
reviewer can see at once which professional vocabulary a document uses.
| Domain | Meaning |
| --- | --- |
| it | Software and IT |
| medical | Healthcare and medical devices |
| construction | Construction and civil engineering |
| Artifact types | Register | Written in the PO language |
| --- | --- | --- |
| 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.
+131
View File
@@ -0,0 +1,131 @@
# Business Case
## Metadata
| Key | Value |
| --- | --- |
| ID | BC-001 |
| CrossReference | [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Executive Summary
Day 40 of Udemy's "100 Days of Code: The Complete Python Pro Bootcamp" turns the Day 39 flight-deal finder into a small flight club. The program now searches direct flights first and falls back to flights with stopovers, reads a customer list from a second Google Sheet ("users"), and sends every customer an email with the deal through SMTP. This project delivers that program as a tested, documented Python 3.13+ repository, built on the code of the `039-personal-flight-club` repository, for the course participant and for other participants who compare solutions.
## Methodological and Standards Foundation
The work follows the SQA and QC framework mounted at `framework/`: artifacts are reviewed against QC checklists tagged with ISO/IEC 25010:2023 characteristics, and code follows the `coding-conventions` and `clean-architecture` skills. Source code carries Doxygen comments and is tested with pytest.
## Problem Statement
The Day 39 program reports only the cheapest flight found, and says nothing about stopovers. Many popular destinations have no direct flight, so they are reported as "N/A". The deals reach only the participant, by WhatsApp; the club's customers, who sign up in a Google Form, get nothing. The starter files of the lesson use Twilio, which this participant replaced in Day 39 and does not want to bring back.
## Business Opportunity
A club that mails every member the best deal, direct or with stops, is a complete small product and a portfolio piece. Other participants (S02) and GitHub visitors (S03) get readable code with the assignment's function names and clear run instructions.
## Objectives
1. Search direct flights first (`check_flights(..., is_direct=True)`); when none is found, search again with stopovers, and record the number of stops in `FlightData.stops`.
2. Read the customer emails from the "users" sheet with `DataManager.get_customer_emails()`; all environment variables, including both sheet endpoints, are read in `DataManager.__init__()`.
3. Send every customer an email through SMTP with `NotificationManager.send_emails()`, with a different message for a direct flight and for a flight with a stopover; the text uses "GBP" and is encoded as UTF-8.
4. Keep every secret in `.env` and never in the repository; keep the Day 39 response cache so free-tier quotas last.
5. Publish a documented repository: README with screenshots, wiki in English, Danish and Bahasa Malaysia with screenshots, Doxygen configuration, CI workflows, description and topics.
## Scope
### In Scope
- A Python 3.13+ project with `src/` and `tests/`, `pyproject.toml`, a local `.venv`, pytest, `constants.py`, a Doxyfile and a Python `.gitignore`, starting from the Day 39 code.
- The assignment's classes and names: `DataManager` with `get_customer_emails()`, `FlightSearch.check_flights()` with `is_direct`, `FlightData` with `stops`, `NotificationManager.send_emails()`, and `main.py`.
- The WhatsApp message of Day 39 stays; the email is added next to it.
- README from the framework template, a three-language wiki, screenshots, CI workflows from the TirSystem workflow repository, repository description and topics.
### Out of Scope
- Twilio SMS or WhatsApp, which the Day 39 project replaced.
- A sign-up form or website (the Google Form is outside the repository) and email address validation beyond a basic format check.
- Automated tests that call the real Sheety, SerpAPI, mock-flight, SMTP or WhatsApp services, or that read the real `.env`.
- A database, scheduling of the daily run, unsubscribe handling and booking of flights.
## Expected Benefits
### Tangible Benefits
- A working, runnable lesson solution with automated tests.
- A repository other participants can clone and run from the README alone.
### Intangible Benefits
- Practice with `smtplib`, environment secrets, API fallbacks and a second data source.
- A reusable template for later course days.
## Strategic Alignment
The project supports the participant's learning goal (completing the bootcamp) and the shared goal of publishing readable solutions that others can learn from.
## Success Criteria
| # | Criterion | Target | Measure |
| --- | --- | --- | --- |
| 1 | Unit tests pass | 100% of tests pass, no network or `.env` access | `pytest` exit code 0 |
| 2 | Indirect fallback | When the direct search finds nothing, a search with stops runs and `stops` is set | Unit test on `main` and `check_flights` |
| 3 | Customer emails | `get_customer_emails()` returns the list of addresses from the users sheet | Unit test with a fake HTTP response |
| 4 | Email content | Direct and stopover messages differ; text holds price, origin, destination, dates, stops and no "£" | Unit test on the message text |
| 5 | Run instructions work | A fresh clone runs by following the README steps only | Manual run of the README steps |
| 6 | Repository metadata and wiki | Description and at least 5 topics set; en, da and ms wiki pages with screenshots | Check on the git host and file review |
| 7 | Runtime dependencies | Only packages the assignment needs; none added over Day 39 | `pyproject.toml` review |
## Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| Free-tier quotas run out (SerpAPI 100/month, Sheety 200/month) | Development stops | Keep the response cache; use the mock flight service; keep 3 to 5 destinations; the extra indirect search runs only when no direct flight exists |
| Secrets committed by mistake | Credential leak | `.env` and cache files in `.gitignore`; only `.env.example` committed; secret scan before each PR |
| SMTP credentials are not yet in the local `.env` | Real mails cannot be sent | SMTP is isolated in `NotificationManager`; tests use a fake `smtplib`; the missing values are an open issue in the Project Plan |
| Mails sent to real customers by mistake during development | Spam to real people | Tests never send; README tells the participant to use a test sheet first |
| CI workflows from the TirSystem repository do not fit this project | Red pipeline | Install only the needed workflows; stop and report after three failed fixes |
## Assumptions
- The Day 39 code is the base. Its WhatsApp delivery (`pywhatkit`, optional and lazy) and the mock flight service remain; Twilio is not restored.
- The Sheety project exposes a `prices` sheet (`city`, `iataCode`, `lowestPrice`, `id`) and a `users` sheet filled by a Google Form (`firstName`, `lastName`, `email`); both use Bearer authentication.
- The participant (S01) is Product Owner, developer and reviewer; in autonomous mode the AI acts as stand-in reviewer and every such review says so.
- The origin airport is LHR and the currency is GBP, both constants, as in the assignment.
- Real tokens exist only in the participant's local `.env`, are used by the participant's own runs and by the repository setup on the git host, and never by tests. The AI uses only the git host token, to set the description and topics.
## Constraints
- Python 3.13 or newer; `venv`; pytest; a `constants.py` for constants; `pyproject.toml` for configuration.
- Doxygen comments in source and a Doxyfile.
- Hosted at `https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code` (this project is the `040-personal-flight-club` repository); one branch and pull request per step.
- No more runtime dependencies than needed; `smtplib` is part of the standard library.
## Cost–Benefit Assessment
| Costs | Benefits |
| --- | --- |
| The participant's spare time; free-tier API accounts; AI assistance | A finished lesson solution, a portfolio repository and a reusable template. Qualitative assessment: the project is small and the cost is time only. |
## Stakeholders
| Stakeholder ID (SA) | Interest in this project |
| --- | --- |
| S01 | Finish the lesson, own the product and review it |
| S02 | Compare solutions; runnable code with the assignment's names |
| S03 | Browse for ideas; clear description, topics and README |
## Recommendation
Proceed — the scope is small, builds on working Day 39 code, the risks are mitigated, and the result serves all three stakeholders.
---
[SA-001]: ./stakeholder-analysis.md
@@ -0,0 +1,71 @@
# MIL-001 Baseline and project setup
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-001 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
Decide whether the repository skeleton is ready for the Day 40 changes: Day 39 code carried over, tooling, configuration, secrets handling, CI and repository metadata.
## Deliverable
A Python 3.13+ project: pyproject.toml, src/ and tests/ layout with the Day 39 code and tests, constants.py, .gitignore, .env.example, Doxyfile, venv instructions, framework hooks, CI workflows from TirSystem/github-action, and the repository description and topics.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `pytest` runs in a fresh `.venv` and passes the carried-over Day 39 tests | Passes | Fails |
| 2 | `.env` and cache files are ignored; only `.env.example` is tracked | Verified with `git check-ignore` | Secret tracked |
| 3 | Installed CI workflows are present and pass on the pull request | Green | Red after 3 fixes |
| 4 | Repository description and at least 5 topics are set | Set | Missing |
## Dependencies
| Depends on | Reason |
| --- | --- |
| None | First phase; the baseline documents (BC, SA, PP) are accepted before it |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objectives 4 and 5 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-26 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Carry over the Day 39 code | Copy `src/flight_club/` and `tests/` from the `039-personal-flight-club` repository (same package and names) into this project and set the project name and description for Day 40 in `pyproject.toml` (Python >=3.13; runtime dependencies requests, requests-cache, python-dotenv; extras `whatsapp` and `dev`). Use `constants.py` for constants. Do not copy `.env`, caches or `.venv`. | No | |
| 2 | Ignore file and env template | Add a Python `.gitignore` (also `.env`, `flight_cache.sqlite`, `.venv`, Doxygen output) and `.env.example` listing variable names without values. The real `.env` holds the participant's tokens and is never committed, tested or read by tests. | No | |
| 3 | Doxygen configuration | Add a `Doxyfile` that scans `src/` and writes to a git-ignored folder; source files use Doxygen comments. | No | |
| 4 | Install CI workflows | Install the workflows that fit from https://git.tirsystem.com/TirSystem/github-action (tests, quality, English-comments check, wiki publish, milestone sync) into `.gitea/workflows/`. Stop and report if they cannot fit. | No | |
| 5 | Framework git hooks | Run `install-git-hooks.sh` with the plan gate enabled so commits to src/ and tests/ need a Task trailer. | No | |
| 6 | Repository description and topics | Set the description and topics on the `040-personal-flight-club` repository through the host API with the local `GITEA_TOKEN`, read from `.env` by a script and never printed or put on a command line. | No | |
---
[BC-001]: ../business-case.md
@@ -0,0 +1,69 @@
# MIL-002 Flight data and indirect search
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-002 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
Decide whether the flight search handles destinations without direct flights (assignment Step 3).
## Deliverable
`FlightData` with a `stops` attribute; `FlightSearch.check_flights(origin_city_code, destination_city_code, from_time, to_time, is_direct=True)` using the SerpAPI `stops` parameter (and the mock provider's equivalent); `main.py` falling back to an indirect search with the assignment's console messages.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `FlightData.__init__()` takes `stops` and stores it; stops are computed as `len(flight["flights"]) - 1` | Unit tests pass | Missing or wrong |
| 2 | `check_flights(..., is_direct=True)` sends the nonstop filter, and `is_direct=False` sends the filter that allows 1 or 2 stops | Unit test on the request parameters | Wrong parameters |
| 3 | `main` prints "Getting direct flights for [city]..." and, when the price is "N/A", "No direct flight to [city]. Looking for indirect flights..." and searches with `is_direct=False` | Unit test with fakes | No fallback |
| 4 | No test uses the network or the real `.env` | Verified | Violated |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-001 | Builds on the previous phase |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 1 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-29 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | FlightData stops | Add `stops` to `FlightData.__init__()` and to the "N/A" result. Compute `nr_stops = len(flight["flights"]) - 1` when parsing a response. | No | |
| 2 | check_flights with is_direct | Add the `is_direct=True` parameter. Direct: SerpAPI `stops=1` (nonstop only). Indirect: the SerpAPI value for up to 1 or 2 stops; the mock provider filters by number of stops. Pass the stops to `FlightData`. Keep the response cache. | No | |
| 3 | Indirect fallback in main | For each destination, search direct first; if `cheapest_flight.price == "N/A"`, print the fallback message and search again with `is_direct=False`. Keep the Day 39 price comparison, sheet update and WhatsApp message. | No | |
| 4 | Tests for stops and fallback | Unit tests for parsing the stops, the request parameters of both searches and the fallback logic, using fakes only. | No | |
---
[BC-001]: ../business-case.md
@@ -0,0 +1,69 @@
# MIL-003 Customer emails
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-003 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
Decide whether the customer list can be read from the second sheet (assignment Step 4).
## Deliverable
`DataManager` that reads all environment variables (token, prices endpoint, users endpoint) in `__init__()` and has `get_customer_emails()` returning the data of the "users" sheet; `.env.example` lists the new endpoint.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `DataManager.__init__()` reads every environment variable in one place | Verified in code and test | Variables read elsewhere |
| 2 | `get_customer_emails()` returns the users' data and the list of email addresses | Unit test with a fake response | Fails |
| 3 | `.env.example` lists the prices and users endpoints without values | Present | Missing |
| 4 | No test uses the network or the real `.env` | Verified | Violated |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-002 | Builds on the previous phase |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 2 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-31 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Settings in DataManager.__init__ | Read `SHEETY_PRICES_ENDPOINT`, `SHEETY_USERS_ENDPOINT` and the authentication variables in `__init__()`. Keep `SHEETY_ENDPOINT` working as a fallback for the prices endpoint so Day 39 `.env` files keep running. | No | |
| 2 | get_customer_emails | Add `get_customer_emails()` that returns the rows of the "users" sheet and a helper that extracts the email addresses (column name from a constant, `email`), skipping rows without a valid-looking address. | No | |
| 3 | Tests for DataManager | Unit tests with a fake `requests` session for both sheets. | No | |
| 4 | Env template | Add the users endpoint to `.env.example`. | No | |
---
[BC-001]: ../business-case.md
@@ -0,0 +1,69 @@
# MIL-004 Email notifications and main program
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-004 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
Decide whether customers receive the flight deal by email (assignment Step 5).
## Deliverable
`NotificationManager` that reads all its environment variables (SMTP address, email, app password, WhatsApp number) in `__init__()` and has `send_emails()`; `main.py` crafts a direct-flight or a stopover message and sends it to all customers.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `NotificationManager.__init__()` reads every environment variable in one place | Verified in code and test | Variables read elsewhere |
| 2 | `send_emails(email_list, message)` logs in through `smtplib` with the app password and sends to every address, UTF-8 encoded | Unit test with a fake `smtplib.SMTP` | Fails |
| 3 | `main` writes a different message for a direct flight and for a flight with a stopover; the text uses "GBP" and holds price, origin, destination, dates and, for a stopover, the number of stops | Unit test on the text | Same text or "£" used |
| 4 | No test sends mail or reads the real `.env` | Verified | Violated |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-003 | Builds on the previous phase |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objectives 2 and 3 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-11-04 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | SMTP settings in NotificationManager | Read `SMTP_ADDRESS`, `EMAIL_ADDRESS`, `EMAIL_PASSWORD` and the WhatsApp number in `__init__()`; add them to `.env.example`. The SMTP port is a constant. | No | |
| 2 | send_emails | Implement `send_emails(email_list, email_body)` with `smtplib` and STARTTLS; build the message as UTF-8 so non-ASCII characters do not fail; one message per customer, with a subject line. | No | |
| 3 | Message text in main | Craft the direct and stopover messages (stops in the stopover text) using "GBP"; send the WhatsApp message and the emails when a cheaper flight is found. | No | |
| 4 | Tests for email and messages | Unit tests with a fake SMTP class and tests of both message texts. | No | |
---
[BC-001]: ../business-case.md
@@ -0,0 +1,69 @@
# MIL-005 Documentation and wiki
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-005 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
Decide whether the repository is ready for participants and visitors.
## Deliverable
README from the framework template with run and test instructions and screenshots; wiki pages in English, Danish and Bahasa Malaysia with screenshots; Doxygen check; `.venv` and `python -m pip install --upgrade pip` instructions.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | README follows the framework template and `check-readme.sh` passes | Passes | Fails |
| 2 | README documents creating and using `.venv` and `python -m pip install --upgrade pip`, running the program and running the tests | Present | Missing |
| 3 | Wiki pages exist in en, da and ms, each with a screenshot | All present | Any missing |
| 4 | `doxygen` runs with the Doxyfile without errors | No errors | Errors |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-004 | Builds on the previous phase |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 5 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-11-07 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Screenshots | Capture a sample run (mock data, no real addresses) and a test run, as images in `docs/images/`. Never show tokens or real email addresses. | No | |
| 2 | README | Fill the framework README template: description, features, installation with `.venv` and `python -m pip install --upgrade pip`, `.env` setup, usage, tests, screenshots, licence. | No | |
| 3 | Wiki in three languages | Write Home and Getting-Started pages in English, Danish and Bahasa Malaysia under `docs/wiki/`, with a sidebar, for the publish workflow. | No | |
| 4 | Doxygen check | Run Doxygen on the Doxyfile and fix warnings in the source comments. | No | |
---
[BC-001]: ../business-case.md
+96
View File
@@ -0,0 +1,96 @@
# Project Plan
## Metadata
| Key | Value |
| --- | --- |
| ID | PP-001 |
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Purpose
This plan schedules the five phases that deliver the Day 40 flight club (see [BC-001]) in a two-week window. One branch and one pull request per milestone keep track of the steps.
## Planning Assumptions
- The plan starts 2026-10-24 and ends by 2026-11-07.
- Each phase ends in a pull request that closes its issues; the Product Owner is S01 ([SA-001]).
- Autonomous mode: after the user accepts this plan, the AI creates, reviews as stand-in for S01, commits and merges each phase.
- Tests never use the real `.env`, the network, SMTP or the WhatsApp session.
## Gateway Schedule
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Baseline and project setup | [MIL-001] | 2026-10-24 to 2026-10-26 | 2026-10-26 | S01 | none | Project skeleton, Day 39 code base, CI, repository metadata | |
| Flight data and indirect search | [MIL-002] | 2026-10-26 to 2026-10-29 | 2026-10-29 | S01 | none | FlightData.stops, check_flights with is_direct, indirect fallback in main | |
| Customer emails | [MIL-003] | 2026-10-29 to 2026-10-31 | 2026-10-31 | S01 | none | DataManager reads the users sheet and all settings in __init__ | |
| Email notifications and main program | [MIL-004] | 2026-10-31 to 2026-11-04 | 2026-11-04 | S01 | none | NotificationManager.send_emails and the final main flow | |
| Documentation and wiki | [MIL-005] | 2026-11-04 to 2026-11-07 | 2026-11-07 | S01 | none | README, wiki en/da/ms, screenshots | |
```plantuml
@startgantt
Project starts 2026-10-24
[Baseline and project setup] starts 2026-10-24 and ends 2026-10-26
[Flight data and indirect search] starts 2026-10-26 and ends 2026-10-29
[Customer emails] starts 2026-10-29 and ends 2026-10-31
[Email notifications and main program] starts 2026-10-31 and ends 2026-11-04
[Documentation and wiki] starts 2026-11-04 and ends 2026-11-07
[MIL-001 Go/No-Go] happens 2026-10-26
[MIL-002 Go/No-Go] happens 2026-10-29
[MIL-003 Go/No-Go] happens 2026-10-31
[MIL-004 Go/No-Go] happens 2026-11-04
[MIL-005 Go/No-Go] happens 2026-11-07
@endgantt
```
## Scope Coverage
| Business Case scope item | Gateway |
| --- | --- |
| Day 39 code carried over, pyproject, constants, .gitignore, Doxyfile, venv | [MIL-001] |
| CI workflows, repository description and topics | [MIL-001] |
| FlightData stops, check_flights with is_direct, indirect fallback | [MIL-002] |
| DataManager.get_customer_emails and settings in __init__ | [MIL-003] |
| NotificationManager.send_emails, direct and stopover messages, main.py | [MIL-004] |
| README, wiki in en/da/ms, screenshots | [MIL-005] |
## Dependencies
```
MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005
```
A No-Go on a phase moves every later date by the rework time.
## Plan Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| CI workflows need changes or a runner the host lacks | MIL-001 slips | Install only fitting workflows; stop and report after three failed fixes |
| Screenshots cannot be captured without real data | MIL-005 slips | Use mock data and a test run only |
| SMTP values are missing from the local `.env` | Real mails cannot be sent | Tests use fakes; the participant adds the values before a real run |
## Open Issues
- The local `.env` has no SMTP address, email address or app password, and no "users" sheet endpoint; they are needed only for a real run, not for the build or the tests.
- The users sheet column names are assumed to be `firstName`, `lastName` and `email` (Sheety camel-cases the Google Form headings); the participant can correct them before acceptance.
- The lesson's starter zip uses Twilio; this project keeps the Day 39 `pywhatkit` WhatsApp delivery instead, as the Business Case records.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[MIL-001]: ./milestones/mil-001-baseline-and-setup.md
[MIL-002]: ./milestones/mil-002-flight-data-and-indirect-search.md
[MIL-003]: ./milestones/mil-003-customer-emails.md
[MIL-004]: ./milestones/mil-004-email-notifications-and-main.md
[MIL-005]: ./milestones/mil-005-documentation-and-wiki.md
+67
View File
@@ -0,0 +1,67 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-001 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | Cost-benefit is qualitative and the table says why (small project, cost is time only). |
| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table has five risks, each with impact and mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Seven success criteria with targets and measures. |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | In Scope and Out of Scope subsections present. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Stakeholders table cites S01, S02, S03 only; no inline role descriptions. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodology and standards section names the framework, ISO/IEC 25010 and coding skills. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate lists. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation is a single 'Proceed' with rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[BC-001]: ../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,67 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-002 |
| CrossReference | [SA-001], [QC-SA-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [SA-001]
- Checklist used: [QC-SA-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | Power, Interest and Quadrant filled for S01 to S03. |
| 2 | Each stakeholder is assigned a unique, stable ID (e.g. S01-S11 style) reusable for RACI assignments in other artifacts | Pass | Stable IDs S01, S02, S03. |
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Roles, organisations and explicit levels given. |
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication table ties each stakeholder to a milestone. |
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Two conflicts, each with a mitigation. |
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Traceability table maps concerns to [BC-001] objectives. |
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Concerns are in business language with a FURPS+ attribute. |
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | Short, plain tables; each stakeholder can find their entry. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[SA-001]: ../../docs/stakeholder-analysis.md
[QC-SA-001]: ../../../framework/qc/artifacts/qc-stakeholder-analysis.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,65 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-003 |
| CrossReference | [MIL-001], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-001]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go/No-Go table has numbered, checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table present. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to [BC-001] objectives. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date set inside the 2026-10-24 to 2026-11-07 plan window. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[MIL-001]: ../../docs/milestones/mil-001-baseline-and-setup.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,65 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-004 |
| CrossReference | [MIL-002], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-002]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go/No-Go table has numbered, checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table present. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to [BC-001] objectives. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date set inside the 2026-10-24 to 2026-11-07 plan window. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[MIL-002]: ../../docs/milestones/mil-002-flight-data-and-indirect-search.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,65 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-005 |
| CrossReference | [MIL-003], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-003]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go/No-Go table has numbered, checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table present. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to [BC-001] objectives. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date set inside the 2026-10-24 to 2026-11-07 plan window. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[MIL-003]: ../../docs/milestones/mil-003-customer-emails.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,65 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-006 |
| CrossReference | [MIL-004], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-004]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go/No-Go table has numbered, checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table present. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to [BC-001] objectives. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date set inside the 2026-10-24 to 2026-11-07 plan window. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[MIL-004]: ../../docs/milestones/mil-004-email-notifications-and-main.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
@@ -0,0 +1,65 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-007 |
| CrossReference | [MIL-005], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-005]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in reads the language and knows the domain)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go/No-Go table has numbered, checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table present. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to [BC-001] objectives. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date set inside the 2026-10-24 to 2026-11-07 plan window. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Language `en` and Domain `it` rows are in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is BCP 47; `it` is in the registry domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register matches the registry row for this type. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The project has no domain dictionary (DICT); the document uses standard IT terms consistently, with no synonyms. Stand-in judgement. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no language change. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by the stand-in for S01 (Product Owner, IT domain). Mode: autonomous, not independent. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | Optional: SMTP, API, CI and similar abbreviations are not all spelled out on first use. Action item below. |
## Overall Verdict
Go — all mandatory criteria pass; the one failed criterion is optional (QC-LANG-001 criterion 10) and has an action item.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Spell out the abbreviations (SMTP, API, CI, IATA) on first use in the README glossary | S01 | 2026-11-07 |
---
[MIL-005]: ../../docs/milestones/mil-005-documentation-and-wiki.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
+79
View File
@@ -0,0 +1,79 @@
# Stakeholder Analysis
## Metadata
| Key | Value |
| --- | --- |
| ID | SA-001 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | pending |
---
## Purpose
This analysis names the people the flight club serves, so owners, reviewers and the documentation can cite stable IDs. It uses the Power/Interest grid.
## Stakeholder Summary Table
| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| S01 | Jens Tirsvad Nielsen | Course participant; Product Owner, developer and reviewer | Private | HIGH | HIGH | Manage Closely | A working, well-documented lesson solution that is cheap to run |
| S02 | Udemy coursists | Fellow course participants | Udemy course community | LOW | MEDIUM | Keep Informed | Readable, runnable code with the assignment's function names, and README run instructions |
| S03 | GitHub viewers | Repository visitors | Public | LOW | LOW | Monitor | A clear description, topics and README, and no extra runtime dependencies |
## Power/Interest Classification Rationale
- **Manage Closely (S01):** decides scope, writes and reviews everything.
- **Keep Informed (S02):** cannot change the project, but copies and compares the code, so readability and instructions matter.
- **Monitor (S03):** casual visitors; the repository front page is enough.
## Primary Concerns and FURPS+ Mapping
| ID | Concern | FURPS+ attribute |
| --- | --- | --- |
| S01 | Emails and messages carry correct deal data, with stops | Functionality |
| S01 | Free-tier quotas are not wasted | Performance |
| S01 | Secrets stay out of the repository; no mail to real people from tests | Functionality (security) |
| S02 | Assignment names kept; code readable | Supportability |
| S02 | Run steps work on a fresh clone | Usability |
| S03 | Description, topics, README, wiki in three languages | Usability |
| S03 | No runtime dependencies beyond the assignment | Supportability |
## Communication Requirements
| ID | Channel | Frequency | Deliverable | Phase / Milestone |
| --- | --- | --- | --- | --- |
| S01 | Chat and run summary | Per milestone | Run summary with RC records and stand-in decisions | All |
| S02 | README and wiki | On release | Run instructions, wiki pages | MIL-005 |
| S03 | Repository page | On release | Description, topics, README, screenshots | MIL-001, MIL-005 |
## Conflicting Interests and Mitigations
| Conflict | Stakeholders | Mitigation |
| --- | --- | --- |
| S02 wants the assignment's structure; clean architecture would reshape it | S01, S02 | Keep the assignment's class and function names; put them in thin modules over a small `src/` package |
| S03 wants no dependencies; WhatsApp and caching need packages | S01, S03 | Runtime: `requests`, `requests_cache`, `python-dotenv`; WhatsApp module optional and lazy; SMTP uses the standard library; dev tools only in the dev extra |
## Traceability Analysis
### Business Goal Alignment
| Stakeholder | Concern | Business Case objective |
| --- | --- | --- |
| S01 | Correct deals, quota, secrets | [BC-001] objectives 1 to 4 |
| S02 | Readable, runnable code | [BC-001] objectives 2, 3 and 5 |
| S03 | Findable repository | [BC-001] objective 5 |
## Sign-Off
Reviewer: S01 (the AI acts as stand-in in autonomous mode, recorded in the RC record).
---
[BC-001]: ./business-case.md
Submodule
+1
Submodule framework added at eca2514787