|
| 1 | +--- |
| 2 | +description: "Code review instructions for the eligibility-signposting-api project" |
| 3 | +applyTo: "**" |
| 4 | +excludeAgent: ["coding-agent"] |
| 5 | +--- |
| 6 | + |
| 7 | +# Code Review Instructions |
| 8 | + |
| 9 | +Guidelines for the eligibility-signposting-api project — a serverless AWS Lambda + Flask eligibility rules engine. |
| 10 | + |
| 11 | +## Review Priorities |
| 12 | + |
| 13 | +### Critical (block merge) |
| 14 | + |
| 15 | +- **Security**: Exposed secrets, PII leakage (especially NHS Numbers), missing header validation |
| 16 | +- **Correctness**: Logic errors in rules engine evaluation, incorrect operator behaviour, data corruption in DynamoDB |
| 17 | +- **Breaking Changes**: API contract changes to FHIR response models or request validation |
| 18 | + |
| 19 | +### Important (requires discussion) |
| 20 | + |
| 21 | +- **Code Quality**: SOLID violations, excessive duplication |
| 22 | +- **Test Coverage**: Missing tests for critical paths, new rules/operators, or edge cases |
| 23 | +- **Performance**: Unnecessary DynamoDB scans, missing caching, Lambda cold start regressions |
| 24 | +- **Architecture**: Deviations from established patterns (wireup DI, chain of responsibility, operator registry) |
| 25 | + |
| 26 | +### Suggestion (non-blocking) |
| 27 | + |
| 28 | +- **Readability**: Naming, simplification of complex logic |
| 29 | +- **Best Practices**: Minor convention deviations |
| 30 | +- **Documentation**: Missing or incomplete docstrings |
| 31 | + |
| 32 | +## Security |
| 33 | + |
| 34 | +- **PII handling**: NHS Numbers must never appear in logs or error messages. `TokenError` messages must be redacted. Verify new log statements do not leak person data. |
| 35 | +- **Secrets**: No API keys, tokens, or secrets in code. Use environment variables or AWS Secrets Manager. |
| 36 | +- **NHS Number hashing**: Lookups use HMAC-SHA512 via `HashingService` with secret rotation (AWSCURRENT → AWSPREVIOUS fallback). |
| 37 | +- **Header validation**: `NHSE-Product-ID` must be present (403 if missing). `nhs-login-nhs-number` must match path parameter. |
| 38 | +- **Security headers**: Responses must include `Cache-Control: no-store, private`, `Strict-Transport-Security`, `X-Content-Type-Options: nosniff`. |
| 39 | + |
| 40 | +## Architecture |
| 41 | + |
| 42 | +- **Dependency injection**: Use wireup `@service` for all services, repos, and factories. Inject via `Injected[T]`, `Inject(qualifier=...)`, or `Inject(param=...)`. Never instantiate services manually. |
| 43 | +- **Chain of responsibility**: Processing follows `CohortEligibilityHandler → BaseEligibilityHandler → FilterRuleHandler → SuppressionRuleHandler`. Extend this chain for new steps. |
| 44 | +- **Operator registry**: New operators must extend `hamcrest.BaseMatcher` and register via the decorator-based `OperatorRegistry`. |
| 45 | +- **Pydantic models**: Use `Field(alias=...)` for JSON mapping, `field_validator`/`model_validator` for validation. Response models use camelCase aliases. |
| 46 | +- **FHIR compliance**: Error responses must use `OperationOutcome` models with `application/fhir+json` content type. |
| 47 | +- **Lambda reuse**: The Flask app is cached in `CacheManager` across invocations. Changes to app initialization must not break container reuse. |
| 48 | + |
| 49 | +## Performance |
| 50 | + |
| 51 | +- **DynamoDB**: Use `query()` with `KeyConditionExpression`, never `scan()`. Partition key is `NHS_NUMBER`, sort key discriminator is `ATTRIBUTE_TYPE`. |
| 52 | +- **S3 configuration loading**: Campaign configs load from S3 per request. Avoid unnecessary `list_objects` or `get_object` calls. |
| 53 | +- **Caching**: Feature toggles use `TTLCache` (300s). New caching should follow the same pattern with appropriate TTLs. |
| 54 | +- **Lambda cold starts**: Avoid heavy imports at module level. Keep wireup service graph lean. |
| 55 | + |
| 56 | +## Audit Trail |
| 57 | + |
| 58 | +- **Completeness**: New eligibility logic must call `AuditContext.append_audit_condition()` to record evaluation details. |
| 59 | +- **Firehose delivery**: Audit events use Pydantic `AuditEvent` models sent to Kinesis Firehose. Preserve the full audit data model. |
| 60 | + |
| 61 | +## Terraform |
| 62 | + |
| 63 | +- **Encryption**: All AWS resources (DynamoDB, S3, Lambda, Firehose, Secrets Manager) must use KMS CMK encryption. |
| 64 | +- **Environment parity**: Verify deletion protection and PITR are enabled for production/pre-production DynamoDB tables. |
| 65 | +- **Safety**: Terraform changes must not destroy or replace stateful resources (DynamoDB tables, S3 buckets) unintentionally. |
0 commit comments