2025-07-17 - 2025-08-17
Overview
73 issues closed from 1 user
Closed
#20 20. The system shall store only the Google user ID, display name, and email hash, never the raw OAuth access token.
Closed
#22 22. The Billing page shall display current plan, remaining quota, next renewal date, and an "Upgrade" button.
Closed
#23 23. The Upgrade flow shall open a Stripe Checkout session in a modal.
Closed
#24 24. Successful Stripe webhooks shall update the User's plan field and reset their quota counter immediately.
Closed
#25 25. Cancellation in Stripe shall downgrade the user to Basic at the period's end and persist renamed files already created.
Closed
#26 26. The Dashboard shall feature a drag‑and‑drop zone that accepts only .jpg, .jpeg, .png, .gif, and .webp MIME types.
Closed
#27 27. The client shall block any drag event containing > N files, where N = user's remaining monthly quota.
Closed
#28 28. The client shall compute SHA‑256 checksums of files to avoid duplicate uploads in the same batch.
Closed
#29 29. After drop, the client shall POST a multipart/form‑data request to /api/batch containing files and raw Keyword Set.
Closed
#30 30. The server shall persist the raw binary files to an object‑store bucket under a time‑based UUID folder.
Closed
#31 31. The server shall enqueue one background job per image for AI Vision processing.
Closed
#32 32. The server shall respond synchronously with a batch_id and an initial status of "PROCESSING".
Closed
#33 33. The "Enhance keywords with AI" button shall be disabled until at least one keyword is typed.
Closed
#34 34. Pressing the button shall call /api/keywords/enhance with the current Keyword Set and target locale "en‑US".
Closed
#35 35. The enhancement endpoint shall invoke an LLM that returns up to ten additional, SEO‑relevant keywords ranked by search volume.
Closed
#36 36. The client shall merge and de‑duplicate the Enhanced Keyword Set before re‑rendering the chip‑list UI.
Closed
#37 37. Users can manually delete any auto‑suggested keyword before upload.
Closed
#38 38. Each background job shall send the image to a vision API (e.g., OpenAI Vision or Google Vision) requesting labels and confidence scores.
Closed
#39 39. The system shall discard any label below 0.40 confidence.
Closed
#40 40. The remaining labels shall form the AI Vision Descriptor list for that image.
Closed
#41 41. The server shall combine Enhanced Keyword Set + AI Vision Descriptor into a ranked pool, giving 70 % weight to Vision tags and 30 % to user keywords when resolving conflicts.
Closed
#42 42. The final pool shall be truncated to a maximum of six distinct, natural‑language tokens.
Closed
#43 43. The Proposed Filename shall start with an uppercase letter and contain only letters, numbers, spaces, and hyphens.
Closed
#44 44. The Proposed Filename shall always exclude stop‑words such as "the", "a", "an", "and".
Closed
#45 45. The Proposed Filename shall be ≤ 60 characters long, excluding the original extension.
Closed
#46 46. The Proposed Filename shall never duplicate within the same batch; a numeric suffix " (2)" shall be appended when collisions occur.
Closed
#47 47. The Proposed Filename shall always include at least one token derived from the AI Vision Descriptor.
Closed
#48 48. The Proposed Filename shall always include at least one token derived from the user's original Keyword Set.
Closed
#49 49. When all jobs in a batch reach status "DONE", the client shall auto‑navigate to /batch/{batch_id}/review.
Closed
#50 50. The Review Table shall display columns: Thumbnail, Original Name, Proposed Filename (editable inline), and Vision Tags (tooltip).
Closed
#51 51. Editing a Proposed Filename shall update the entry's state to "CUSTOM".
Closed
#52 52. Pressing "Regenerate this name" on a row shall re‑run the naming algorithm with a new random seed.
Closed
#53 53. The "Download ZIP" button shall remain disabled until at least one row exists and no rows are in "PROCESSING".
Closed
#54 54. Clicking "Download ZIP" shall trigger a GET to /api/batch/{batch_id}/zip; the server shall stream a ZIP archive containing renamed files.
Closed
#55 55. The ZIP archive shall preserve original EXIF metadata.
Closed
#56 56. A usage table shall store one row per successfully renamed image with columns user_id, timestamp, and byte_size.
Closed
#57 57. The server shall decrement the user's remaining quota atomically at the start of each job.
Closed
#58 58. At UTC 00:00 on the first of each month, a cron job shall reset every user's quota to their plan limit.
Closed
#59 59. All public pages shall score ≥ 90 on Google Lighthouse performance and accessibility audits.
Closed
#60 60. The API shall respond to the /healthz probe in < 150 ms 95th percentile.
Closed
#61 61. All endpoints shall enforce HTTPS via HSTS with a max‑age of 31536000 s.
Closed
#62 62. Uploaded files shall be scanned by ClamAV; detections shall abort processing and log an alert.
Closed
#63 63. The server shall store all secrets in environment variables managed by a secrets manager, never in the repo.
Closed
#64 64. The system shall support horizontal scaling by keeping all session state in stateless JWTs and Redis.
Closed
#65 65. Background queues shall run idempotent jobs retried with exponential backoff up to five attempts.
Closed
#66 66. The landing‑page hero shall feature a single‑sentence value proposition followed by a "Try it free" call‑to‑action.
Closed
#67 67. The Dashboard shall show a quota progress bar with a numeric fraction like "23 / 50 images used".
Closed
#68 68. Drag‑and‑drop zone shall highlight when files hover over it and display the total number accepted.
Closed
#69 69. Invalid files shall be listed with a red icon and a tooltip reason like "GIF over 25 MB rejected".
Closed
#70 70. While Vision jobs run, each Proposed Filename cell shall display a looping shimmer placeholder animation.
Closed
#71 71. The billing modal shall summarise price, billing frequency, and confirm upgrade in ≤ three clicks.
Closed
#72 72. All user‑facing times shall be displayed in the user's browser locale, derived via Intl.DateTimeFormat.
Closed
#73 73. POST /api/batch → { batch_id, accepted_count, skipped_count }.
Closed
#74 74. GET /api/batch/{batch_id}/status → { state: PROCESSING|DONE|ERROR, progress: 0‑100 }.
Closed
#75 75. PUT /api/image/{image_id}/filename accepts { new_name } and returns the updated record.
Closed
#76 76. POST /api/keywords/enhance accepts { keywords[] } and returns { enhanced_keywords[] }.
Closed
#77 77. WebSocket ws://…/progress/{batch_id} streams JSON events { image_id, status }.
Closed
#81 81. payments: id, user_id, stripe_session_id, plan, amount, currency, status.
Closed
#82 82. All API calls shall log trace IDs compatible with OpenTelemetry.
Closed
#83 83. Errors shall be sent to Sentry with user ID redacted.
Closed
#84 84. Batch processing time per image shall be exported as a Prometheus histogram.
Closed
#85 85. All interactive controls shall be reachable via keyboard and labelled with aria‑label.
Closed
#86 86. The app shall support English only in V1, but all text shall be pulled from a translation JSON to allow later localisation.
Closed
#87 87. The app shall be containerised in a multi‑stage Dockerfile producing a final Alpine image < 300 MB.
Closed
#88 88. CI shall run ESLint, Prettier, unit tests, and Cypress e2e tests on every pull request.
Closed
#80 80. images : id, batch_id, original_name, proposed_name, vision_tags jsonb, status.
Closed
#79 79. batches : id, user_id, status, created_at.
Closed
#78 78. users : id, google_uid, email_hash, plan, quota_remaining, created_at.
Closed
#89 89. Production shall run on Kubernetes with separate pods for API, worker, and front‑end static hosting.
Closed
#90 90. Zero‑downtime deploys shall be achieved with rolling updates and readiness probes.
Closed
#91 91. Every sentence numbered 10‑90 defines a single, atomic requirement that an LLM can verify by querying the deployed system's observable behaviour, data, or codebase.
Closed
#92 92. A compliance suite shall map each requirement ID to a unit‑test prompt following the pattern: "Assert that requirement NN is satisfied by …".
Closed
#21 21. Password‑based logins are explicitly out of scope for V1.
83 issues created by 1 user
Opened
#10 10. The product shall let any authenticated user rename many images in one batch using a combination of user‑supplied keywords and automatic computer‑vision tags.
Opened
#11 11. The product shall output renamed images that are search‑engine‑friendly, syntactically safe for all major file systems, and semantically descriptive of image content.
Opened
#12 12. The product shall monetise via tiered monthly quotas and Stripe‑handled subscriptions.
Opened
#13 13. Anonymous visitors can view the marketing landing page but cannot upload images.
Opened
#14 14. Basic users can upload ≤ 50 images per month and access all core renaming features.
Opened
#15 15. Pro users inherit Basic rights and raise the quota to 500 images per month.
Opened
#16 16. Max users inherit Basic rights and raise the quota to 1 000 images per month.
Opened
#17 17. Administrators can view global usage stats, force‑reset quotas, refund payments, and ban accounts.
Opened
#18 18. The sign‑in button shall initiate Google OAuth 2.0 with email scope only.
Opened
#19 19. The system shall create a new User record on first successful OAuth callback.
Opened
#20 20. The system shall store only the Google user ID, display name, and email hash, never the raw OAuth access token.
Opened
#21 21. Password‑based logins are explicitly out of scope for V1.
Opened
#22 22. The Billing page shall display current plan, remaining quota, next renewal date, and an "Upgrade" button.
Opened
#23 23. The Upgrade flow shall open a Stripe Checkout session in a modal.
Opened
#24 24. Successful Stripe webhooks shall update the User's plan field and reset their quota counter immediately.
Opened
#25 25. Cancellation in Stripe shall downgrade the user to Basic at the period's end and persist renamed files already created.
Opened
#26 26. The Dashboard shall feature a drag‑and‑drop zone that accepts only .jpg, .jpeg, .png, .gif, and .webp MIME types.
Opened
#27 27. The client shall block any drag event containing > N files, where N = user's remaining monthly quota.
Opened
#28 28. The client shall compute SHA‑256 checksums of files to avoid duplicate uploads in the same batch.
Opened
#29 29. After drop, the client shall POST a multipart/form‑data request to /api/batch containing files and raw Keyword Set.
Opened
#30 30. The server shall persist the raw binary files to an object‑store bucket under a time‑based UUID folder.
Opened
#31 31. The server shall enqueue one background job per image for AI Vision processing.
Opened
#32 32. The server shall respond synchronously with a batch_id and an initial status of "PROCESSING".
Opened
#33 33. The "Enhance keywords with AI" button shall be disabled until at least one keyword is typed.
Opened
#34 34. Pressing the button shall call /api/keywords/enhance with the current Keyword Set and target locale "en‑US".
Opened
#35 35. The enhancement endpoint shall invoke an LLM that returns up to ten additional, SEO‑relevant keywords ranked by search volume.
Opened
#36 36. The client shall merge and de‑duplicate the Enhanced Keyword Set before re‑rendering the chip‑list UI.
Opened
#37 37. Users can manually delete any auto‑suggested keyword before upload.
Opened
#38 38. Each background job shall send the image to a vision API (e.g., OpenAI Vision or Google Vision) requesting labels and confidence scores.
Opened
#39 39. The system shall discard any label below 0.40 confidence.
Opened
#40 40. The remaining labels shall form the AI Vision Descriptor list for that image.
Opened
#41 41. The server shall combine Enhanced Keyword Set + AI Vision Descriptor into a ranked pool, giving 70 % weight to Vision tags and 30 % to user keywords when resolving conflicts.
Opened
#42 42. The final pool shall be truncated to a maximum of six distinct, natural‑language tokens.
Opened
#43 43. The Proposed Filename shall start with an uppercase letter and contain only letters, numbers, spaces, and hyphens.
Opened
#44 44. The Proposed Filename shall always exclude stop‑words such as "the", "a", "an", "and".
Opened
#45 45. The Proposed Filename shall be ≤ 60 characters long, excluding the original extension.
Opened
#46 46. The Proposed Filename shall never duplicate within the same batch; a numeric suffix " (2)" shall be appended when collisions occur.
Opened
#47 47. The Proposed Filename shall always include at least one token derived from the AI Vision Descriptor.
Opened
#48 48. The Proposed Filename shall always include at least one token derived from the user's original Keyword Set.
Opened
#49 49. When all jobs in a batch reach status "DONE", the client shall auto‑navigate to /batch/{batch_id}/review.
Opened
#50 50. The Review Table shall display columns: Thumbnail, Original Name, Proposed Filename (editable inline), and Vision Tags (tooltip).
Opened
#51 51. Editing a Proposed Filename shall update the entry's state to "CUSTOM".
Opened
#52 52. Pressing "Regenerate this name" on a row shall re‑run the naming algorithm with a new random seed.
Opened
#53 53. The "Download ZIP" button shall remain disabled until at least one row exists and no rows are in "PROCESSING".
Opened
#54 54. Clicking "Download ZIP" shall trigger a GET to /api/batch/{batch_id}/zip; the server shall stream a ZIP archive containing renamed files.
Opened
#55 55. The ZIP archive shall preserve original EXIF metadata.
Opened
#56 56. A usage table shall store one row per successfully renamed image with columns user_id, timestamp, and byte_size.
Opened
#57 57. The server shall decrement the user's remaining quota atomically at the start of each job.
Opened
#58 58. At UTC 00:00 on the first of each month, a cron job shall reset every user's quota to their plan limit.
Opened
#59 59. All public pages shall score ≥ 90 on Google Lighthouse performance and accessibility audits.
Opened
#60 60. The API shall respond to the /healthz probe in < 150 ms 95th percentile.
Opened
#61 61. All endpoints shall enforce HTTPS via HSTS with a max‑age of 31536000 s.
Opened
#62 62. Uploaded files shall be scanned by ClamAV; detections shall abort processing and log an alert.
Opened
#63 63. The server shall store all secrets in environment variables managed by a secrets manager, never in the repo.
Opened
#64 64. The system shall support horizontal scaling by keeping all session state in stateless JWTs and Redis.
Opened
#65 65. Background queues shall run idempotent jobs retried with exponential backoff up to five attempts.
Opened
#66 66. The landing‑page hero shall feature a single‑sentence value proposition followed by a "Try it free" call‑to‑action.
Opened
#67 67. The Dashboard shall show a quota progress bar with a numeric fraction like "23 / 50 images used".
Opened
#68 68. Drag‑and‑drop zone shall highlight when files hover over it and display the total number accepted.
Opened
#69 69. Invalid files shall be listed with a red icon and a tooltip reason like "GIF over 25 MB rejected".
Opened
#70 70. While Vision jobs run, each Proposed Filename cell shall display a looping shimmer placeholder animation.
Opened
#71 71. The billing modal shall summarise price, billing frequency, and confirm upgrade in ≤ three clicks.
Opened
#72 72. All user‑facing times shall be displayed in the user's browser locale, derived via Intl.DateTimeFormat.
Opened
#73 73. POST /api/batch → { batch_id, accepted_count, skipped_count }.
Opened
#74 74. GET /api/batch/{batch_id}/status → { state: PROCESSING|DONE|ERROR, progress: 0‑100 }.
Opened
#75 75. PUT /api/image/{image_id}/filename accepts { new_name } and returns the updated record.
Opened
#76 76. POST /api/keywords/enhance accepts { keywords[] } and returns { enhanced_keywords[] }.
Opened
#77 77. WebSocket ws://…/progress/{batch_id} streams JSON events { image_id, status }.
Opened
#78 78. users : id, google_uid, email_hash, plan, quota_remaining, created_at.
Opened
#79 79. batches : id, user_id, status, created_at.
Opened
#80 80. images : id, batch_id, original_name, proposed_name, vision_tags jsonb, status.
Opened
#81 81. payments: id, user_id, stripe_session_id, plan, amount, currency, status.
Opened
#82 82. All API calls shall log trace IDs compatible with OpenTelemetry.
Opened
#83 83. Errors shall be sent to Sentry with user ID redacted.
Opened
#84 84. Batch processing time per image shall be exported as a Prometheus histogram.
Opened
#85 85. All interactive controls shall be reachable via keyboard and labelled with aria‑label.
Opened
#86 86. The app shall support English only in V1, but all text shall be pulled from a translation JSON to allow later localisation.
Opened
#87 87. The app shall be containerised in a multi‑stage Dockerfile producing a final Alpine image < 300 MB.
Opened
#88 88. CI shall run ESLint, Prettier, unit tests, and Cypress e2e tests on every pull request.
Opened
#89 89. Production shall run on Kubernetes with separate pods for API, worker, and front‑end static hosting.
Opened
#90 90. Zero‑downtime deploys shall be achieved with rolling updates and readiness probes.
Opened
#91 91. Every sentence numbered 10‑90 defines a single, atomic requirement that an LLM can verify by querying the deployed system's observable behaviour, data, or codebase.
Opened
#92 92. A compliance suite shall map each requirement ID to a unit‑test prompt following the pattern: "Assert that requirement NN is satisfied by …".