CMP-340 · Lesson 12 of 12 · 35 min
Capstone: a team software project from requirements to release
This capstone ties the course together by following one invented team project from first meeting to first release, then closing with the professional responsibilities that come with building software for other people: ethics, licensing, intellectual property, accessibility, privacy and the use of AI coding assistants. The client is the Riverside Community Food Bank, a charity with three locations, about 400 active volunteers and two paid staff, which wants to replace its paper sign-up sheets and phone reminders. The team is four students working over one term, with the food bank's volunteer coordinator acting as product owner. Each section points back to the lesson that covered the technique in depth, so the capstone also works as a review. CMPUT-401 will put you on real projects like this one; CMPUT-499 is the computing science capstone.
Inception: vision, stakeholders and scope
The first two weeks are about understanding the problem, not writing code. The team writes a one-paragraph product vision ('For volunteers and coordinators at Riverside who struggle with paper sign-ups and missed shifts, the Riverside Scheduler is a web application that lets volunteers find and sign up for shifts and receive reminders, unlike the current phone-and-paper process') and a stakeholder map. Stakeholders include volunteers of many ages, some on old phones and some using screen readers; coordinators at each location; the board, which reports volunteer hours to the city for a grant; the parents of teenage volunteers; and the food bank's one IT volunteer, who will run the system after the students leave. That last stakeholder is easy to forget and shapes the architecture more than anyone else.
Elicitation (lesson 3) uses interviews with two coordinators, observation of a Saturday sign-up morning, the city's grant reporting form and a short questionnaire to volunteers. The team writes the resulting needs as user stories with Given/When/Then acceptance criteria, records non-functional requirements with numbers, and agrees an explicit out-of-scope list, because 'won't have this time' prevents scope creep later. The biggest risks are identified early: the text-message provider's cost and consent rules, the IT volunteer's limited capacity, and the privacy of minors' data.
| Need | Story or requirement | Priority |
|---|---|---|
| Volunteers find and book shifts | As a volunteer, I want to sign up for an open shift online, so that I can choose shifts without phoning | Must |
| Fewer no-shows | As a volunteer, I want an email reminder the day before, so that I do not forget | Must |
| Grant reporting | As a coordinator, I want monthly hours by program in the city's format | Must |
| Teenage volunteers | As a parent, I want to approve my child's volunteering before they can sign up | Must |
| Full shifts | As a volunteer, I want to join a waiting list for a full shift | Should |
| Text reminders | As a volunteer, I want an optional text reminder | Could |
| Accessibility | All volunteer pages meet WCAG 2.1 AA, tested with a screen reader | Must (non-functional) |
| Operability | The IT volunteer can deploy an update with one command and restore from backup in under an hour | Must (non-functional) |
| Shift swaps | Volunteers swap shifts directly | Won't have this term |
Process and team agreements
The team chooses two-week sprints (lesson 2), because the coordinator can meet every two weeks for a review, and writes down its working agreements in the first week: how decisions are made, when the team meets, expected response time on pull requests, and how disagreements are escalated. Roles rotate: one student acts as Scrum master for the term, and each sprint a different student takes the lead on releasing. The team writes a definition of done that every story must meet before the coordinator sees it.
| Definition of done item | Checked by |
|---|---|
| Acceptance criteria met and demonstrated | Product owner at review |
| Code reviewed and approved by another team member | Branch protection rule |
| Unit and integration tests written and passing; new code covered | CI pipeline |
| Lint, format and type checks pass | CI pipeline |
| Accessibility checks pass (axe) and keyboard walkthrough done for new pages | CI plus reviewer |
| Deployed to staging and smoke-tested | Pipeline and release lead |
| User-facing changes noted in the changelog; ADR written for significant decisions | Reviewer |
Estimation and the release plan
The team sizes the backlog with planning poker in story points (lesson 4), using 'reminder email' as a 3-point reference. Before any velocity history exists, it forecasts conservatively from a capacity estimate (four students, each with about eight hours a week for the course project) and plans to revise after two sprints. After sprint 2, it replaces the guess with a Monte Carlo forecast from its actual velocities and shows the coordinator which stories are very likely, likely and unlikely to make the end of term. The plan is ordered by value and risk, so the riskiest piece, parental consent for minors, which touches privacy, email verification and the sign-up rules, is built in sprint 2 rather than left to the end.
import random
random.seed(301)
velocities = [14, 19] # points done in sprints 1 and 2
remaining_by_priority = [("Must", 44), ("Should", 16), ("Could", 13)]
sprints_left = 4
def chance_to_finish(points):
"""Share of simulated futures that finish `points` within the remaining sprints."""
hits = 0
for _ in range(10000):
done = sum(random.choice(velocities) * random.uniform(0.85, 1.15)
for _ in range(sprints_left))
hits += done >= points
return hits / 10000
total = 0
for label, pts in remaining_by_priority:
total += pts
print(f"all {label:6s} items ({total:2d} points): {chance_to_finish(total):6.1%}")all Must items (44 points): 100.0% all Should items (60 points): 84.2% all Could items (73 points): 12.1%
With only two data points the forecast is rough, and the team says so, adding small random variation to avoid overconfidence. But it already tells the coordinator something useful: the Must items are very likely, the Should items reasonable, and text reminders probably not this term. That conversation, held in week five rather than week twelve, is the whole point of forecasting.
Architecture and design
The architecture (lesson 6) follows from the stakeholders: the IT volunteer can operate one server and one database, so the team builds a modular monolith in Django with PostgreSQL, organized into accounts, shifts, notifications and reporting modules, with dependency rules checked in CI. Reminders go through a background job queue so that a slow email provider never blocks a sign-up. The team records these choices in architecture decision records, starting with the one shown in lesson 6. It sketches a class diagram of the domain and a state machine for sign-ups (lesson 5), and implements the state machine as a transition table with a test for every transition, which later catches a missing 'canceled by organizer' state when a snowstorm closes a location.
Building, reviewing and integrating
Development follows GitHub Flow (lesson 8): short-lived branches, small pull requests with a description and test notes, at least one review, and squash merges onto a protected main branch. The pipeline (lesson 11) runs Ruff, mypy, unit tests and accessibility checks on every pull request in about four minutes, and on merge builds a container image, runs integration tests against PostgreSQL and deploys to a staging server. Code review uses the checklist from lesson 8, with particular attention to privacy: no volunteer phone numbers or minors' details in logs. Refactoring happens continuously (lesson 7): when the report module grows a flag argument for 'monthly' versus 'by program', a reviewer asks for it to be split, as in lesson 7's worked example.
The test strategy (lessons 9 and 10) follows the pyramid: unit tests for the sign-up, waiting-list and consent rules with boundaries such as the last confirmed and first waitlisted sign-up; integration tests for the repository and migrations; three end-to-end tests for the critical journeys (sign up, cancel, monthly report) in a real browser; a property-based test that sign-ups never exceed capacity under any sequence of sign-ups and cancellations; and a short mutation-testing run on the domain module before each release.
Release and handover
The first production release goes out in sprint 4 to one location only, a staged rollout behind a feature flag (lesson 11), with paper sheets kept as a fallback for two weeks. The team monitors sign-up errors and email delivery and holds a short blameless review of the one incident, a reminder job that sent duplicate emails after a restart, fixed by making the job idempotent (lesson 6). Before handing over, the team automates a release checklist, writes an operations runbook for the IT volunteer (deploy, roll back, restore a backup, rotate the email provider key), and walks through a real restore together, because a backup that has never been restored is only a hope.
# An automated pre-release checklist: each check returns (passed, detail)
release = {
"version": "1.0.0", "tests_passed": 412, "tests_failed": 0, "coverage_new_code": 0.91,
"open_critical_bugs": 0, "axe_violations": 0, "migrations_reversible": True,
"changelog_has_version": True, "backup_restore_tested_days_ago": 6,
"dependencies_with_known_vulnerabilities": ["oldlib 0.9 (low severity)"],
}
checks = {
"all tests pass": (release["tests_failed"] == 0, f'{release["tests_passed"]} passed'),
"new code covered >= 80%": (release["coverage_new_code"] >= 0.80, f'{release["coverage_new_code"]:.0%}'),
"no open critical bugs": (release["open_critical_bugs"] == 0, "0 open"),
"no accessibility violations": (release["axe_violations"] == 0, "axe clean"),
"migrations reversible": (release["migrations_reversible"], "down-migrations tested"),
"changelog updated": (release["changelog_has_version"], release["version"]),
"restore tested in 30 days": (release["backup_restore_tested_days_ago"] <= 30,
f'{release["backup_restore_tested_days_ago"]} days ago'),
"no high-severity vulnerabilities": (all("low" in d for d in
release["dependencies_with_known_vulnerabilities"]),
"; ".join(release["dependencies_with_known_vulnerabilities"])),
}
for name, (ok, detail) in checks.items():
print(f"[{'x' if ok else ' '}] {name:34s} {detail}")
print("READY TO RELEASE" if all(ok for ok, _ in checks.values()) else "NOT READY")[x] all tests pass 412 passed [x] new code covered >= 80% 91% [x] no open critical bugs 0 open [x] no accessibility violations axe clean [x] migrations reversible down-migrations tested [x] changelog updated 1.0.0 [x] restore tested in 30 days 6 days ago [x] no high-severity vulnerabilities oldlib 0.9 (low severity) READY TO RELEASE
Professional practice: ethics in the project
The ACM and IEEE Computer Society Software Engineering Code of Ethics from lesson 1 puts the public interest first, and the capstone raises several concrete cases. The coordinator asks the team to show volunteers' phone numbers to every other volunteer so they can arrange swaps; the code's principles on privacy and on acting in the public interest suggest the team explain the risk and propose an alternative, such as in-app messages or opt-in sharing. Near the end of term, a team member finds that the monthly report double-counts volunteers who worked two shifts on the same day; the code's principle of honesty means telling the client, fixing it and checking whether past reports sent to the city were affected, even though the demo is next week. And when the team is tempted to skip accessibility testing to finish a feature, the definition of done, and the law described in lesson 3, settle the question.
For American students, these obligations are mostly professional rather than legal. As lesson 1 explained, the title software engineer is generally unrestricted and the PE exam in software engineering was discontinued in 2019, but the ACM Code of Ethics and the joint Software Engineering Code are widely referenced by employers, and safety-critical domains are governed by regulators such as the FAA and FDA. Some states restrict the word engineer in business names or public advertising, so check your state board's rules before offering engineering services.
Licensing and intellectual property
Two intellectual-property questions arise in every client project: who owns the code the team writes, and are the team's dependencies' licenses compatible with how the code will be used? Ownership depends on the agreement. By default copyright belongs to the authors, but employment contracts, contractor agreements and many university project agreements assign it to an employer, client or the university, so the team signs a short agreement with the food bank before writing code. Here the food bank wants the code to be open source so that other food banks can use it. CMPUT-201 lesson 12 introduced permissive and copyleft licenses; the team chooses the Apache License 2.0, a permissive license with an explicit patent grant, and adds a LICENSE file, a CONTRIBUTING guide and copyright headers. FILM-420 covers copyright law itself in more depth.
Every dependency comes with its own license, and some combinations conflict. Permissive licenses (MIT, BSD, Apache 2.0) can be combined with almost anything. Strong copyleft licenses such as the GPL require that a distributed combined work be released under the GPL, so a GPL dependency cannot be used in a proprietary product that is distributed; Apache 2.0 code can be combined into GPL version 3 works but is considered incompatible with GPL version 2. The AGPL extends copyleft to software offered over a network, which matters for web applications. Tools such as pip-licenses, ScanCode and FOSSA list dependencies' licenses automatically; the small audit below shows the idea.
# A simplified dependency licensing audit for a project released under Apache-2.0
PROJECT = "Apache-2.0"
compatible_with_apache = {"MIT", "BSD-3-Clause", "BSD-2-Clause", "Apache-2.0", "PSF-2.0",
"ISC", "LGPL-3.0"} # LGPL is fine when used as a separate library
deps = {"django": "BSD-3-Clause", "psycopg": "LGPL-3.0", "requests": "Apache-2.0",
"celery": "BSD-3-Clause", "pdfgen-lite": "GPL-3.0", "tzdata": "Apache-2.0",
"map-widget": "AGPL-3.0", "colorlog": "MIT"}
problems = {d: lic for d, lic in deps.items() if lic not in compatible_with_apache}
for d, lic in sorted(deps.items()):
print(f"{d:12s} {lic:13s} {'REVIEW' if d in problems else 'ok'}")
print(f"\n{len(problems)} dependencies need review before release under {PROJECT}:")
for d, lic in problems.items():
print(f" {d}: {lic} is copyleft; distributing or hosting the combined work may require "
f"releasing it under {lic}")celery BSD-3-Clause ok colorlog MIT ok django BSD-3-Clause ok map-widget AGPL-3.0 REVIEW pdfgen-lite GPL-3.0 REVIEW psycopg LGPL-3.0 ok requests Apache-2.0 ok tzdata Apache-2.0 ok 2 dependencies need review before release under Apache-2.0: pdfgen-lite: GPL-3.0 is copyleft; distributing or hosting the combined work may require releasing it under GPL-3.0 map-widget: AGPL-3.0 is copyleft; distributing or hosting the combined work may require releasing it under AGPL-3.0
The audit flags two dependencies for review, and the team replaces the GPL PDF library with a permissively licensed one and drops the AGPL map widget, which the coordinator did not really need. Real license compliance has more nuance than any table: how a library is linked, whether the software is distributed, and specific license exceptions all matter, and organizations with significant exposure consult lawyers. When the team contributes fixes back to an upstream project, it follows that project's CONTRIBUTING guide, which may require signing a contributor license agreement (CLA) or adding a Developer Certificate of Origin (DCO) sign-off line to each commit.
AI coding assistants
AI coding assistants now write a significant share of code in many teams, and the course's practices apply to their output exactly as to human code. The team adopts a written policy. Generated code is reviewed and tested like any other contribution, and the person who submits it is responsible for it. No client data, credentials or volunteers' personal information may be pasted into external AI services, because that may breach the privacy commitments in lesson 3 and the client agreement. Suggestions that reproduce substantial code from elsewhere must be checked against license obligations; some tools offer filters that block suggestions matching public code. Security deserves extra care, because generated code can contain injection flaws, outdated cryptography or invented package names that attackers register, so dependency names suggested by an assistant are verified before installation. And because the copyright status of purely AI-generated material remains unsettled in both Canada and the United States, as FILM-420 and PHOT-420 discuss, the team records significant AI assistance in pull request descriptions and keeps human authorship of the design. Academic integrity rules for the course take precedence over all of this: follow your instructor's policy on what assistance is allowed.
Retrospective and what comes next
At the end of each sprint, and once more at the end of term, the team holds a retrospective (lesson 2). A useful format asks what went well, what did not, and what the team will try next, with one or two concrete actions rather than a long list. The final retrospective for this project noted that early forecasting kept the client's expectations realistic, that the definition of done prevented an accessibility backlog, and that pull requests waited too long for review in weeks with exams, which the team addressed by agreeing to review within one working day and keeping pull requests small. It also measured itself: lead time from first commit to production fell from 11 days in sprint 2 to 2 days in sprint 6, and the change failure rate was one in fourteen deployments.
Worked problem
Responding to a late requirement
In week 9 of 12, the board asks for the monthly report to also show hours by volunteer age group, for a new grant. The team has 13 points of capacity left, all planned for Should items. What should the team do?
Show solution
- Treat it as a new story: understand the need (which age groups, what format, what deadline) and size it with the team, perhaps 5 points, plus a privacy review because ages of minors are sensitive.
- Show the product owner the trade-off: adding it means dropping 5 points of Should items, such as part of the waiting list, unless the date moves.
- Check the privacy implications: report only aggregated counts per age band, suppress bands with very few people so individuals cannot be identified, and confirm the grant requires this.
- Let the product owner decide, update the backlog and forecast, and record the decision.
Answer: Late requirements are normal; the process absorbs them through explicit trade-offs, estimation and a privacy check, rather than silent overtime or quietly dropping quality.
Worked problem
An ethical dilemma near the deadline
Two days before the final demo, a team member discovers that parents' approval emails are not being sent when the parent's address has uppercase letters, so some minors were able to sign up for shifts without approval. Fixing it properly means delaying a planned feature demo. What does the Software Engineering Code of Ethics suggest?
Show solution
- Public interest and client interest: the defect undermines a safety and consent requirement for minors, so it takes priority over a feature demo.
- Honesty: tell the coordinator now, explain the impact, and identify affected sign-ups from the database.
- Fix with a test: normalize email addresses, add regression tests for mixed-case addresses, and require approval for the affected minors before their next shift.
- Process improvement: add the case to boundary and equivalence tests for email handling, and discuss in the retrospective how it slipped through.
Answer: Disclose, fix with a regression test, remediate the affected sign-ups and improve the process. Delaying a demo is a small cost compared with breaking a consent promise to parents.
Common mistakes
MistakeStarting to code before understanding stakeholders and scope.
InsteadSpend the first weeks on vision, stakeholders, elicitation and an explicit out-of-scope list.
MistakeForgetting the people who will operate the system.
InsteadDesign for the actual operators: simple deployment, runbooks and tested restores.
MistakeUsing dependencies without checking their licenses.
InsteadAudit licenses early and choose a project license deliberately, with agreement on who owns the code.
MistakePasting client data into external AI tools or accepting generated code unreviewed.
InsteadFollow a written AI policy: no confidential data, full review and testing, license and security checks, and the course's academic integrity rules.
MistakeHiding defects to protect a demo.
InsteadDisclose promptly, fix with tests and remediate, as the code of ethics requires.
Summary and key terms
- A capstone project starts with a vision, stakeholder map, elicitation and a prioritized backlog with an explicit out-of-scope list.
- Team agreements and a definition of done make quality expectations explicit from the first sprint.
- Estimates become forecasts once velocity data exists; ordering by value and risk tackles the riskiest work early.
- Architecture follows from quality attributes and operators' capabilities, recorded in ADRs; state machines and class diagrams guide the design.
- GitHub Flow, code review, an automated pipeline and a balanced test suite keep the main branch releasable.
- Staged releases, monitoring, runbooks and tested restores make handover to the client safe.
- Professional practice covers ethics, regulation of titles, code ownership, license compatibility, accessibility, privacy and responsible use of AI assistants.
- Product vision
- A short statement of who the product is for, the problem it solves and how it differs from alternatives.
- Working agreement
- A team's explicit agreement about how it collaborates.
- Runbook
- Step-by-step instructions for operating tasks such as deploying, rolling back and restoring.
- Staged rollout
- Releasing to a subset of users or locations before everyone.
- Permissive license
- A license such as MIT or Apache 2.0 that allows reuse, including in proprietary software, with few conditions.
- Copyleft license
- A license such as the GPL that requires derivative works to be distributed under the same license.
- License compatibility
- Whether code under different licenses can legally be combined in one work.
- Contributor license agreement
- An agreement granting a project rights to contributors' code.
- Developer Certificate of Origin
- A per-commit sign-off certifying that the contributor has the right to submit the code.
- Retrospective
- A regular meeting in which a team reflects on how it worked and chooses improvements.
Practice problems
Work each problem on paper first, then reveal the answer to check.
Write a product vision statement for a library's room-booking app.
Show answer
For students who struggle to find study rooms, the Room Finder is a mobile web app that shows and books free rooms in real time, unlike the current paper sign-up at each desk.
Why is the food bank's IT volunteer an important stakeholder?
Show answer
They will operate and maintain the system after the team leaves, which constrains the architecture and deployment.
Name three items you would put in a definition of done for this project.
Show answer
Reviewed and approved; tests passing in CI; accessibility checks passed; deployed to staging.
Why build the parental consent feature early?
Show answer
It is the riskiest item, touching privacy, email verification and sign-up rules, so early work leaves time to correct course.
A dependency is licensed under GPL-3.0 and your project is proprietary software distributed to customers. What is the issue?
Show answer
Distributing a combined work would require releasing it under the GPL; replace the dependency or change the licensing plan, with legal advice if needed.
What does an AGPL license add for web applications?
Show answer
Users interacting with the software over a network must be offered the source, not only recipients of distributed copies.
List three rules for using AI coding assistants on a client project.
Show answer
No client data or secrets in external tools; review and test all generated code; verify licenses and package names; follow academic integrity policy.
What should an operations runbook contain?
Show answer
Steps to deploy, roll back, restore from backup, rotate secrets and respond to common alerts.
Give one ethical issue the capstone raised and the response.
Show answer
Sharing volunteers' phone numbers: explain the privacy risk and offer opt-in sharing or in-app messages instead.
What makes a retrospective action useful?
Show answer
It is concrete, owned by someone and checked at the next retrospective.
Lesson quiz · 5 questions
Score 60% or more to complete this lesson.
Create a free account to save your progress, take quizzes and earn a certificate.