Skip to content

Functional test generated by RoostGPT#72

Open
Divyeshzb wants to merge 1 commit into
mainfrom
roost-d6bf0345-379c-48af-b81d-1f8f88aaab5e
Open

Functional test generated by RoostGPT#72
Divyeshzb wants to merge 1 commit into
mainfrom
roost-d6bf0345-379c-48af-b81d-1f8f88aaab5e

Conversation

@Divyeshzb
Copy link
Copy Markdown
Contributor

Please pull these awesome changes in!
Test Name     - functional-test-aegis
AI Type       - Azure Open AI
AI Model      - gpt-5
Test Type     - Functional test
Use Type      - docker_ui
User Language - english

RoostGPT Logs

Copilot AI review requested due to automatic review settings April 28, 2026 07:19
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Roost-generated “functional-test-aegis” bundle under functional_tests/, describing an Aegis Card portal end-to-end journey plus a broad set of security/compliance/transactions/billing functional scenarios.

Changes:

  • Added new test artifacts for functional-test-aegis (JSON spec, Gherkin feature, CSV index, XLSX/DOCX outputs, Roost metadata).
  • Updated functional_tests/README.md to register the new test run and link to its outputs.

Reviewed changes

Copilot reviewed 4 out of 7 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
functional_tests/functional-test-aegis/functional-test-aegis.json Large JSON test catalog describing scenarios, steps, expected results, and assumptions.
functional_tests/functional-test-aegis/functional-test-aegis.feature Gherkin-style feature file mirroring the JSON scenarios for human-readable execution.
functional_tests/functional-test-aegis/functional-test-aegis.csv Flat list of scenario titles for quick indexing.
functional_tests/functional-test-aegis/functional-test-aegis.xlsx Spreadsheet export of the test cases.
functional_tests/functional-test-aegis/functional-test-aegis.docx Document export of the test cases.
functional_tests/functional-test-aegis/.roost/roost_metadata.json Roost metadata capturing inputs and provenance.
functional_tests/README.md Appends an entry for this test run and links to generated outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

{
"type": "e2e-functional",
"title": "Applicant Journey E2E: Register -> Verify -> Login (MFA) -> Application Steps -> APPROVED -> Set PIN -> Summary -> Token Rotation, CSRF, Autosave, Session Timeout",
"description": "Covers full new-user onboarding with regulatory controls: registration validations, email verification, OAuth2 login with TOTP, multi-step credit application with autosave and session_token, approval path, masked PAN, CSRF enforcement, token refresh rotation/reuse detection, session timeout warning and logout.",
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The testDescription/description mentions “OAuth2 login”, but the described flow here uses /v2/auth/login rather than an OAuth2 auth-code/PKCE exchange. Either update the description to match the actual steps, or incorporate the OAuth2 flow (which you already cover in a separate PKCE test case).

Suggested change
"description": "Covers full new-user onboarding with regulatory controls: registration validations, email verification, OAuth2 login with TOTP, multi-step credit application with autosave and session_token, approval path, masked PAN, CSRF enforcement, token refresh rotation/reuse detection, session timeout warning and logout.",
"description": "Covers full new-user onboarding with regulatory controls: registration validations, email verification, login with MFA/TOTP, multi-step credit application with autosave and session_token, approval path, masked PAN, CSRF enforcement, token refresh rotation/reuse detection, session timeout warning and logout.",

Copilot uses AI. Check for mistakes.
"testId": "TC-NOTIFY-VALID-019",
"testDescription": "Ensures webhook input validation and PII masking, channel handling, and UI severity badge mapping operate correctly without idempotency conflicts.",
"prerequisites": "Active account_id for user@example.com; authenticated portal session open to observe in-app notifications; webhook endpoint reachable.",
"stepsToPerform": "1. POST /v2/notifications/webhook with account_id, alert_type 'UNKNOWN_EVENT', channel IN_APP, message_body 'Test', severity INFO, idempotency_key a valid UUID; expect 400 INVALID_ALERT_TYPE.\n2. POST /v2/notifications/webhook with valid alert_type LATE_PAYMENT but channel 'PAGER' (unsupported); expect 400 INVALID_ALERT_TYPE or invalid channel error per spec.\n3. POST /v2/notifications/webhook with alert_type STATEMENT_READY, channel IN_APP, severity INFO, message_body 'Your statement is ready', idempotency_key UUID1; expect 200 notification_id and delivered_at; verify portal shows INFO badge.\n4. POST /v2/notifications/webhook with alert_type OVER_LIMIT, channel EMAIL, severity WARNING, message_body 'Over-limit used on card **** **** **** 1234', idempotency_key UUID2; expect 200 queued or delivered; confirm no full PAN appears in any payload or UI.\n5. POST /v2/notifications/webhook with alert_type FRAUD_FLAG, channel IN_APP, severity CRITICAL, message_body 'Suspicious charge on card 4111 1111 1111 1111 at Merchant X', idempotency_key UUID3; expect 200; verify backend masks PAN in stored/displayed message to **** **** **** 1111 (REQ-014) and portal shows CRITICAL badge.\n6. In portal, refresh the notifications UI and verify exactly three alerts visible with correct types and severities INFO, WARNING, CRITICAL; ensure timestamps are ISO 8601 UTC and sorted by delivered_at.\n7. Attempt to send a very long message_body >500 chars; expect 400 validation error and no alert created.\n8. Confirm that in-app alert payloads contain no PII beyond masked PAN and merchant descriptors; no ssn_last4, address, or tokens present.\n9. Resend the STATEMENT_READY with a different idempotency_key UUID4 but same content; expect 200 and a second distinct alert, proving idempotency depends on key not content.",
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test case embeds a full PAN-like string (4111 1111 1111 1111) inside stepsToPerform. Even if it’s a test number, storing full PAN patterns in-repo can trip PCI/secret scanning and is often disallowed. Prefer a non-PAN placeholder token and keep the masking assertion (e.g., “system must mask any 16-digit sequences”) without including the raw number.

Suggested change
"stepsToPerform": "1. POST /v2/notifications/webhook with account_id, alert_type 'UNKNOWN_EVENT', channel IN_APP, message_body 'Test', severity INFO, idempotency_key a valid UUID; expect 400 INVALID_ALERT_TYPE.\n2. POST /v2/notifications/webhook with valid alert_type LATE_PAYMENT but channel 'PAGER' (unsupported); expect 400 INVALID_ALERT_TYPE or invalid channel error per spec.\n3. POST /v2/notifications/webhook with alert_type STATEMENT_READY, channel IN_APP, severity INFO, message_body 'Your statement is ready', idempotency_key UUID1; expect 200 notification_id and delivered_at; verify portal shows INFO badge.\n4. POST /v2/notifications/webhook with alert_type OVER_LIMIT, channel EMAIL, severity WARNING, message_body 'Over-limit used on card **** **** **** 1234', idempotency_key UUID2; expect 200 queued or delivered; confirm no full PAN appears in any payload or UI.\n5. POST /v2/notifications/webhook with alert_type FRAUD_FLAG, channel IN_APP, severity CRITICAL, message_body 'Suspicious charge on card 4111 1111 1111 1111 at Merchant X', idempotency_key UUID3; expect 200; verify backend masks PAN in stored/displayed message to **** **** **** 1111 (REQ-014) and portal shows CRITICAL badge.\n6. In portal, refresh the notifications UI and verify exactly three alerts visible with correct types and severities INFO, WARNING, CRITICAL; ensure timestamps are ISO 8601 UTC and sorted by delivered_at.\n7. Attempt to send a very long message_body >500 chars; expect 400 validation error and no alert created.\n8. Confirm that in-app alert payloads contain no PII beyond masked PAN and merchant descriptors; no ssn_last4, address, or tokens present.\n9. Resend the STATEMENT_READY with a different idempotency_key UUID4 but same content; expect 200 and a second distinct alert, proving idempotency depends on key not content.",
"stepsToPerform": "1. POST /v2/notifications/webhook with account_id, alert_type 'UNKNOWN_EVENT', channel IN_APP, message_body 'Test', severity INFO, idempotency_key a valid UUID; expect 400 INVALID_ALERT_TYPE.\n2. POST /v2/notifications/webhook with valid alert_type LATE_PAYMENT but channel 'PAGER' (unsupported); expect 400 INVALID_ALERT_TYPE or invalid channel error per spec.\n3. POST /v2/notifications/webhook with alert_type STATEMENT_READY, channel IN_APP, severity INFO, message_body 'Your statement is ready', idempotency_key UUID1; expect 200 notification_id and delivered_at; verify portal shows INFO badge.\n4. POST /v2/notifications/webhook with alert_type OVER_LIMIT, channel EMAIL, severity WARNING, message_body 'Over-limit used on card **** **** **** 1234', idempotency_key UUID2; expect 200 queued or delivered; confirm no full PAN appears in any payload or UI.\n5. POST /v2/notifications/webhook with alert_type FRAUD_FLAG, channel IN_APP, severity CRITICAL, message_body 'Suspicious charge on card [PAN_16_DIGITS] at Merchant X', idempotency_key UUID3; expect 200; verify backend masks any PAN-like 16-digit sequence in stored/displayed message per REQ-014, no unmasked 16-digit sequence appears in payload or UI, and portal shows CRITICAL badge.\n6. In portal, refresh the notifications UI and verify exactly three alerts visible with correct types and severities INFO, WARNING, CRITICAL; ensure timestamps are ISO 8601 UTC and sorted by delivered_at.\n7. Attempt to send a very long message_body >500 chars; expect 400 validation error and no alert created.\n8. Confirm that in-app alert payloads contain no PII beyond masked PAN and merchant descriptors; no ssn_last4, address, or tokens present.\n9. Resend the STATEMENT_READY with a different idempotency_key UUID4 but same content; expect 200 and a second distinct alert, proving idempotency depends on key not content.",

Copilot uses AI. Check for mistakes.
Comment on lines +761 to +763
"prerequisites": "Active account with transactions; authenticated portal session; WebSocket subscription available; statements exist; notifications present that mention card references.",
"stepsToPerform": "1. Navigate to account dashboard; visually confirm card display shows masked PAN like **** **** **** 1234; inspect DOM elements and ensure no hidden full PAN or data attributes contain PAN.\n2. Open browser devtools Network tab and reload dashboard; filter for API calls; verify no response payload contains full PAN; any card references are masked; response caching does not store PAN.\n3. Inspect window.localStorage and sessionStorage; ensure no PAN, ssn_last4, or JWT tokens are stored; only non-sensitive UI preferences allowed.\n4. Navigate to card management UI; verify card number field (if present) is rendered via third-party iframe tokenization component (e.g., Stripe Elements) loaded over TLS 1.3; confirm iframe origin allowlisted by CSP and that host page never receives raw PAN (ASSUMPTION tokenization present).\n5. Create a CAD transaction via POST /v2/accounts/{account_id}/transactions to generate a WebSocket event; verify the event payload in the WebSocket frames contains only masked PAN and necessary merchant/amount fields; no PII or tokens included.\n6. Open latest statement JSON via GET /v2/accounts/{account_id}/statements/{statement_id}; confirm any card references are masked; download PDF format and scan text for patterns matching 16-digit PAN; expect only masked values.\n7. Trigger a notification via POST /v2/notifications/webhook with message_body containing a PAN-like string '4111 1111 1111 1111'; verify stored and rendered message masks to **** **** **** 1111 and no full PAN visible.\n8. In the application flow pages, inspect autosave keys in localStorage; confirm no ssn_last4 or card data stored; only non-sensitive application draft fields are present.\n9. Verify CSP headers in responses disallow inline scripts and restrict iframe sources; ensure all tokenization and API endpoints load over HTTPS TLS 1.3; no mixed content.\n10. Perform DOM and network search for regex patterns resembling PAN (\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b); ensure zero matches across visible content and payload bodies except masked format.",
"expectedResult": "Masked PAN is consistently used across UI, APIs, WebSocket, statements, and notifications; no full PAN appears in DOM, network, or storage; iframe tokenization is present and secure; CSP and TLS policies enforced; autosave contains no sensitive data.",
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section repeats the full PAN-like string (4111 1111 1111 1111) (and also includes a regex intended to find PANs). If you need to test masking behavior, consider using a synthetic placeholder (e.g., PAN_TEST_16DIGITS) and/or a generated value at runtime rather than committing a literal 16-digit sequence in the JSON.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +7
Given the API base URL is 'https://api.aegiscard.com/v2'
And the portal URL is 'https://portal.aegiscard.com'
And the realtime WebSocket URL is 'wss://realtime.aegiscard.com/v2/stream'
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functional_tests/*.feature files consistently parameterize the API host via an environment variable (e.g., functional_tests/test-new-hello/test-new-hello.feature:5, functional_tests/ZBIO-5136/ZBIO-5136.feature:5, functional_tests/ZBIO-5139/ZBIO-5139.feature:6). Hardcoding the API/portal/WebSocket URLs here makes the test artifact less portable and increases the risk of someone running it against the wrong environment. Consider switching these to env-var driven values (and avoid embedding a /v2 suffix in the base so paths stay consistent).

Suggested change
Given the API base URL is 'https://api.aegiscard.com/v2'
And the portal URL is 'https://portal.aegiscard.com'
And the realtime WebSocket URL is 'wss://realtime.aegiscard.com/v2/stream'
Given the API base URL is '${API_BASE_URL}'
And the portal URL is '${PORTAL_URL}'
And the realtime WebSocket URL is '${REALTIME_WS_URL}'

Copilot uses AI. Check for mistakes.
When I POST '/auth/token/refresh' and then POST '/auth/token/refresh' again using the same refresh token
Then the second response status should be 401
And the error code should be 'TOKEN_INVALID'
When I POST '/accounts/<id>' DELETE to exercise Right to Rescind within 14 days with 'X-CSRF-Token'
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step mixes HTTP methods: When I POST '/accounts/<id>' DELETE .... That’s internally inconsistent and will likely break any downstream parser/runner. Update it to a single, correct method (e.g., When I DELETE '/accounts/<id>' ...).

Suggested change
When I POST '/accounts/<id>' DELETE to exercise Right to Rescind within 14 days with 'X-CSRF-Token'
When I DELETE '/accounts/<id>' to exercise Right to Rescind within 14 days with 'X-CSRF-Token'

Copilot uses AI. Check for mistakes.
Comment on lines +569 to +575
| csrf_header | amount | bank_id | scheduled | status | error_code |
| X-CSRF-Token | 1.00 | 11111111-2222-3333-4444-555555555555 | null | 200 | |
| X-CSRF-Token | 0.999 | 11111111-2222-3333-4444-555555555555 | null | 400 | SCALE_INVALID |
| X-CSRF-Token | <tb+0.01>| 11111111-2222-3333-4444-555555555555 | null | 400 | ABOVE_MAX |
| X-CSRF-Token | <tb> | 11111111-2222-3333-4444-555555555555 | "tomorrow" | 200 | |
| (missing) | 5.00 | 11111111-2222-3333-4444-555555555555 | null | 403 | CSRF_MISSING |

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this Scenario Outline, the Examples table uses (missing) as a value for <csrf_header>. Since the step says with headers '<csrf_header>', this can be interpreted as literally adding a header named (missing) rather than omitting CSRF. Consider splitting the missing-CSRF negative into its own scenario/step, or use a dedicated mechanism your runner understands for “omit this header”.

Suggested change
| csrf_header | amount | bank_id | scheduled | status | error_code |
| X-CSRF-Token | 1.00 | 11111111-2222-3333-4444-555555555555 | null | 200 | |
| X-CSRF-Token | 0.999 | 11111111-2222-3333-4444-555555555555 | null | 400 | SCALE_INVALID |
| X-CSRF-Token | <tb+0.01>| 11111111-2222-3333-4444-555555555555 | null | 400 | ABOVE_MAX |
| X-CSRF-Token | <tb> | 11111111-2222-3333-4444-555555555555 | "tomorrow" | 200 | |
| (missing) | 5.00 | 11111111-2222-3333-4444-555555555555 | null | 403 | CSRF_MISSING |
| csrf_header | amount | bank_id | scheduled | status | error_code |
| X-CSRF-Token | 1.00 | 11111111-2222-3333-4444-555555555555 | null | 200 | |
| X-CSRF-Token | 0.999 | 11111111-2222-3333-4444-555555555555 | null | 400 | SCALE_INVALID |
| X-CSRF-Token | <tb+0.01>| 11111111-2222-3333-4444-555555555555 | null | 400 | ABOVE_MAX |
| X-CSRF-Token | <tb> | 11111111-2222-3333-4444-555555555555 | "tomorrow" | 200 | |
@api @payments
Scenario: Payments CUSTOM rejects requests with missing CSRF header
Given total_balance and an active bank_account_id are known
When I POST '/accounts/<account_id>/payments' without the CSRF header and with JSON payload
"""
{"payment_type":"CUSTOM","payment_amount":5.00,"bank_account_id":"11111111-2222-3333-4444-555555555555","scheduled_date":null}
"""
Then the response status should be 403
And the error code should be 'CSRF_MISSING'

Copilot uses AI. Check for mistakes.
Comment on lines +694 to +699
When I POST a FRAUD_FLAG IN_APP alert containing a PAN-like string
"""
{"account_id":"<account_id>","alert_type":"FRAUD_FLAG","channel":"IN_APP","message_body":"Suspicious charge on card 4111 1111 1111 1111 at Merchant X","severity":"CRITICAL","idempotency_key":"<uuid5>"}
"""
Then the response status should be 200
And stored/rendered message masks to '**** **** **** 1111'
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This payload includes a full PAN-like test number (4111 1111 1111 1111). Even if it’s not a real card, committing full PAN patterns can trigger secret/PCI scanners and can violate data-handling policies. Prefer a non-PAN placeholder (e.g., PAN_LIKE_STRING) or a partially masked string, and describe the masking expectation without embedding a 16-digit sequence.

Suggested change
When I POST a FRAUD_FLAG IN_APP alert containing a PAN-like string
"""
{"account_id":"<account_id>","alert_type":"FRAUD_FLAG","channel":"IN_APP","message_body":"Suspicious charge on card 4111 1111 1111 1111 at Merchant X","severity":"CRITICAL","idempotency_key":"<uuid5>"}
"""
Then the response status should be 200
And stored/rendered message masks to '**** **** **** 1111'
When I POST a FRAUD_FLAG IN_APP alert containing a PAN placeholder
"""
{"account_id":"<account_id>","alert_type":"FRAUD_FLAG","channel":"IN_APP","message_body":"Suspicious charge on card PAN_LIKE_STRING at Merchant X","severity":"CRITICAL","idempotency_key":"<uuid5>"}
"""
Then the response status should be 200
And stored/rendered message masks the card reference

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants