Add baseline: Business Case, Stakeholder Analysis, Project Plan and milestones

Refs the three milestones MIL-001 to MIL-003; reviews RC-001 to RC-005 (Go).
This commit is contained in:
2026-10-17 15:11:20 +08:00
parent f8ea3401bd
commit 052008f213
14 changed files with 904 additions and 0 deletions
@@ -0,0 +1,76 @@
# MIL-002 Birthday Wisher Core
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-002 |
| CrossReference | [BC-001], [SA-001], [MIL-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-004 (Go) | pending |
---
## Purpose
Decide whether the birthday wisher works: it finds today's birthdays, builds a letter and sends it, with tests that need no network and no credentials.
## Deliverable
The `birthday_wisher` package: loading `birthdays.csv`, matching today's month and day, choosing a random template and replacing `[NAME]`, sending by SMTP with STARTTLS, a `main` entry point, and a pytest suite. All public items carry Doxygen comments.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `python -m pytest` passes with no network access and without a `.env` file | Go | No-Go |
| 2 | A test proves that a person whose month and day equal today receives exactly one letter and nobody else does | Go | No-Go |
| 3 | A test proves that `[NAME]` is replaced and every one of the three templates can be chosen | Go | No-Go |
| 4 | A test with a fake SMTP object proves STARTTLS is called before login and that the subject is "Happy Birthday" | Go | No-Go |
| 5 | No source or test file imports or reads `.env`; the token is read from the `GMAIL_TOKEN` environment variable only | Go | No-Go |
| 6 | The code is reviewed against `qc-programming-python` and the review record says Go | Go | No-Go |
## Dependencies
| Depends on | Reason |
| --- | --- |
| [MIL-001] | Needs the skeleton, constants and data files |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objectives 1, 2 and 3 | [BC-001] |
| S01, S02 concerns | [SA-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-19 - within the schedule of the Business Case constraints.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Load and match birthdays | Read `birthdays.csv` with the standard `csv` module into a dictionary keyed by `(month, day)` as the course hint describes, and return the people whose key equals today's `(month, day)`. Today is a parameter so tests can fix the date. | No | |
| 2 | Build the letter | Choose one of the letter templates at random (the chooser is injectable for tests), and replace `[NAME]` with the person's name. Fail with a clear message when a template is missing. | No | |
| 3 | Send the letter by SMTP | Send the letter with `smtplib`: connect to the host in `constants.py`, call `starttls()`, log in with the sender address and the `GMAIL_TOKEN` environment variable, and send with the subject "Happy Birthday". The SMTP class is injected; the token is never logged. | No | |
| 4 | Add main entry point | Wire the pieces together in `main.py` (composition root): load, match, build, send. Add a `--dry-run` option that prints instead of sending, used for screenshots and by learners without credentials. Exit with a non-zero status on error. | No | |
| 5 | Write pytest tests | Cover matching, letters, sending with a fake SMTP and the entry point with a fixed date. Tests use temporary files and never touch the network or `.env`. | No | |
| 6 | Review code against the Python checklist | Review `src/` and `tests/` against `qc-programming-python`, write the `RC-*` record and fix findings before the pull request. | No | |
---
[BC-001]: ../business-case.md
[SA-001]: ../stakeholder-analysis.md
[MIL-001]: ./mil-001-project-setup.md