Define an API contract
Model a task-management API with endpoints for creating, reading, updating and deleting tasks. Specify request fields, response shapes and status codes. Validate input at the boundary and distinguish malformed input, missing resources and unauthorized actions.
Store data consistently
Use a database schema with explicit ownership and foreign keys. Parameterize queries instead of concatenating untrusted input. Put related writes in a transaction and test what happens if the second write fails.
Protect user actions
Separate authentication from authorization. A valid login does not mean a user can edit someone else's task. Test object-level permissions, expired sessions and invalid payloads. Keep secrets outside source control and avoid logging passwords or tokens.
Ship a reviewable project
Deliver API documentation, database migrations and tests for successful and failed requests. Add structured logs, health checks and an environment configuration example without credentials. Explain how the application recovers from failed database connections and repeated client requests.
Backend lab: test resource ownership
Create two test users and one task owned by each user. Verify that each can read and change their own task. Then attempt the same operations with the other user's task ID. The API must enforce ownership on the server rather than trusting a hidden button in the interface. Test missing credentials, malformed IDs and valid IDs that do not exist. Record status codes and confirm that responses do not disclose another user's private fields.
Check your progress
Keep your working files, test cases and notes together. Explain one design decision, demonstrate a failure case and list what you would improve next. These concrete outputs make it easier to identify the next skill to practice.