A set of 15 self-contained exercises against the polyglot AssetTrack system. Each exercise can be done independently — completing one does not require another. Each one is a realistic scenario where Copilot is a force multiplier: filling test/doc gaps, fixing seeded bugs, modernizing legacy code, or adding new features.
Services involved in each exercise are tagged in [brackets].
Tip
Before starting, run docker compose up --build from the repo root and confirm every service is reachable. The Astro frontend at http://localhost:4321 is the easiest way to verify the system is alive.
Goal: Build a mental model of the system before changing anything.
The app is split across seven services in three languages (.NET, Java, Python) plus an Astro frontend. Use Copilot to:
- Summarize what each service in
services/*does and which database it owns. - Trace a single user action ("create an assignment") from the Astro page through
workforce-svctonotifications-svc. - List every place data is read or written for a given concept (e.g. "assets").
- Produce a one-page architecture diagram from the source.
Deliverable: A short written summary (in your own notes) of the architecture, data flow, and where each domain concept lives.
Goal: Bring services/assets-svc to meaningful test coverage.
The test project exists (services/assets-svc/Tests/) but only has a smoke test. Use Copilot to author xUnit tests covering:
- Create / read / update / delete happy paths.
- Search by status, by tag, and the stats-by-status endpoint.
- Edge cases: missing fields, unknown ids, empty result sets.
Run with dotnet test services/assets-svc/Tests/AssetsService.Tests.csproj.
Goal: Create a real test suite for services/reporting-svc.
The tests/ directory is intentionally empty. Use Copilot to scaffold pytest and cover:
- Warranty-expiring report: assets within the configurable window are returned, others are not.
- Utilization report: counts match the seeded data.
- CSV import: a well-formed file produces the expected response shape.
Bonus: write a fixture that spins up an isolated SQLite DB so tests don't depend on the running service.
Goal: Eliminate string-concatenation SQL across the two legacy services.
Two known vulnerable methods:
services/auth-svc/.../UserRepository.java—findByUsernamebuilds SQL with+ username +.services/audit-svc/.../AuditRepository.java—searchconcatenates the query into threeLIKEclauses.
Use Copilot to convert each to a PreparedStatement with bind parameters. Add a regression test for audit-svc that proves a payload like ' OR 1=1 -- no longer matches every row.
Goal: Make assets-svc actually enforce the JWTs that auth-svc issues.
auth-svc already issues RS256 JWTs and exposes its public keys at GET /.well-known/jwks. assets-svc currently accepts every request unauthenticated. Use Copilot to:
- Add a JWT authentication handler in
services/assets-svcthat fetches and caches the JWKS fromAUTH_JWKS_URL. - Reject requests without a valid bearer token on write endpoints (POST/PUT/DELETE).
- Update the Astro server-side fetcher (
services/web/src/lib/api/client.ts) to forward the token.
Goal: Bring services/reporting-svc/app/legacy/format_helpers.py up to modern Python conventions.
The module uses % formatting, os.path.join, no type hints, and 2.x-flavored idioms. Use Copilot to:
- Convert to f-strings.
- Use
pathlib.Pathfor file paths. - Add type hints and run
mypy(or just inspect the result). - Replace any deprecated stdlib usage.
Verify nothing that imports the module breaks.
Goal: Modernize services/audit-svc end-to-end.
audit-svc runs on Spring Boot 2.7 and Java 11. Use Copilot to:
- Bump
pom.xmlto Spring Boot 3.x and Java 17 or 21. - Migrate
javax.*imports tojakarta.*. - Update its
Dockerfilebase image. - Run
mvn verifyand fix every failure.
Goal: Apply what you learned in exercise 9 to services/auth-svc.
Same shape as #9 but for the auth service. Watch out for the JJWT dependency — the API changed across major versions, and auth-svc exposes a public JWKS that other services rely on. Don't break the JSON shape of GET /.well-known/jwks.
Goal: Let users filter the assets list by type and status.
assets-svc already has basic search; extend it (or its query parameters) to support combined filters. Update the Astro services/web/src/pages/assets/index.astro page to render a filter form and re-render results based on query string.
Goal: Stop bad data at the door.
POST /assets in services/assets-svc accepts anything. Use Copilot to:
- Add a
Validatoror data-annotations-based validation layer on the .NET side, with helpful error responses. - Show field-level errors on the Astro form at
services/web/src/pages/assets/new.astro. - Required: name, assetTag, assetType, status. Date sanity:
purchaseDate <= warrantyExpires.
Goal: Add GET /assets/by-tag/{tag} (already declared — make sure it's wired and used).
Verify the endpoint in services/assets-svc/Endpoints/AssetEndpoints.cs returns the right asset and 404s correctly. Add a typed client method in services/web/src/lib/api/assets.ts and use it on the asset detail page lookup.
Goal: Build an "Assets by Department" page that composes data from multiple backends.
In services/web, add a new page that:
- Calls
workforce-svcfor employees grouped by department. - Calls
assets-svcfor the assets currently assigned to each employee. - Renders a table grouped by department with totals.
This is a "real" SSR exercise — all fetching happens on the Astro server.
Goal: Wrong status badge colors on the dashboard.
services/web/src/components/StatusBadge.astro maps statuses to colors. Two are wrong:
retiredis shown as green but should be a neutral gray.lostis shown as blue but should be red.
Fix the mapping. Bonus: add a Vitest unit test that proves the mapping is correct.
Goal: Make CSV import resilient.
POST /imports/assets in services/reporting-svc/app/routers/imports_.py crashes if any single row is malformed. Use Copilot to:
- Wrap per-row processing in try/except.
- Return a summary response:
{ "imported": N, "skipped": M, "errors": [...] }. - Add a test that imports
sample_import.csvwith a deliberately broken row and confirms the import still succeeds with one skipped row.
Goal: Persist an audit event whenever an assignment is created or returned.
audit-svc exposes POST /events and is fully functional, but workforce-svc doesn't call it. In services/workforce-svc/.../assignment/AssignmentService.java you'll find a commented-out hook. Use Copilot to:
- Wire an
AuditClientthat posts toAUDIT_SVC_URL. - Send an event on assignment create and on
recordReturn. - Make the call best-effort: a failed audit POST must not fail the user-facing operation.
| # | Title | Primary service(s) | Skill area |
|---|---|---|---|
| 1 | Understand the Codebase | all | Comprehension |
| 2 | Unit tests for assets | assets-svc | Tests |
| 3 | Fix SQL injection | auth-svc, audit-svc | Security |
| 4 | Modernize Python helpers | reporting-svc | Modernization |
| 5 | Asset search/filter | assets-svc, web | Feature |
| 6 | Resilient CSV import | reporting-svc | Error handling |
| 7 | Asset create validation | assets-svc, web | Validation |
| 8 | Dashboard badge bug | web | Bug fix |
| 9 | Upgrade Spring Boot | audit-svc | Modernization |
| 10 | New .NET endpoint | assets-svc, web | Feature |
| 11 | Pytest for reporting | reporting-svc | Tests |
| 12 | Upgrade second legacy service | auth-svc | Modernization |
| 13 | Audit logging hook | workforce-svc, audit-svc | Integration |
| 14 | Validate JWTs | assets-svc, auth-svc | Security |
| 15 | Cross-service Astro page | web, workforce-svc, assets-svc | Feature |