From 4a09be8f6d38fac47eff8def0c48b98f0873bf40 Mon Sep 17 00:00:00 2001 From: Gutierrez Soto Jhosepmyr Orlando Date: Fri, 10 Jul 2026 15:38:45 -0500 Subject: [PATCH 1/3] docs: fix Stripe webhook URL guidance to use app.tamci.app, not api.tamci.app api.tamci.app resolves directly to the CloudFront-only ALB; a webhook pointed there times out with zero trace on the backend (root cause of a real production incident: paid checkout never activated the plan). --- docs/BILLING.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/BILLING.md b/docs/BILLING.md index 55afcecc..461a0555 100644 --- a/docs/BILLING.md +++ b/docs/BILLING.md @@ -108,10 +108,16 @@ For university presentations, demo environments, or staging deployments, **you s Since your deployed application has a public domain name, **you do not need the Stripe CLI (`stripe listen`) running on your server**. Stripe can send the webhook events directly to your public URL: 1. In the Stripe Dashboard (with **Test Mode** turned ON), go to **Developers** ▸ **Webhooks** and click **Add endpoint**. -2. Set the **Endpoint URL** to your deployed backend domain: +2. Set the **Endpoint URL** to your deployed **frontend** domain, not the bare API domain: ```text - https://your-api-domain.com/api/billing/webhooks/stripe + https://app.tamci.app/api/billing/webhooks/stripe ``` + > [!WARNING] + > `api.tamci.app` resolves directly to the ALB, which is locked down to CloudFront-only ingress + > (see [reqsai-infra](https://github.com/Kntro-Soft/reqsai-infra)'s security groups). Stripe's + > servers are not CloudFront, so a webhook pointed at `api.tamci.app` times out silently — no + > log entry on the backend at all, since the request never reaches it. Always use + > `app.tamci.app` (routed through CloudFront) for anything Stripe needs to reach. 3. Click **Select events** and subscribe to: * `checkout.session.completed` * `customer.subscription.deleted` @@ -132,7 +138,8 @@ When deploying to production, apply the following changes: 2. **Products & Prices**: Create the production products and prices in the live dashboard catalog and update `BILLING_*_STRIPE_PRICE_ID` environment variables. 3. **Webhook Registration**: - Go to **Developers** ▸ **Webhooks** ▸ **Add endpoint**. - - Set the URL to your live API endpoint: `https://your-api-domain.com/api/billing/webhooks/stripe`. + - Set the URL to `https://app.tamci.app/api/billing/webhooks/stripe` — **not** `api.tamci.app` + (see the warning above: the bare API domain is CloudFront-only and unreachable from Stripe). - Subscribe to these events: * `checkout.session.completed` (handles purchase / upgrade activation). * `customer.subscription.deleted` (handles cancellation/lapse). From 34ab0f34b59ce1edabd4ae61baf4187385e037cb Mon Sep 17 00:00:00 2001 From: Gutierrez Soto Jhosepmyr Orlando Date: Thu, 8 Oct 2026 14:47:25 -0500 Subject: [PATCH 2/3] fix(gateway): point the dev Jira OAuth callback at the web's settings route application-dev.yml defaulted the Atlassian redirect to /integrations/jira/callback, a route the web does not have; the web callback, the base config, .env.example and the Jira guide all use /settings/integrations/jira/callback. --- CHANGELOG.md | 8 ++++++++ src/main/resources/application-dev.yml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd8c027d..1bbe7908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,14 @@ follows [Semantic Versioning](https://semver.org/). _Bounded-context implementation (iam, billing, workspace, discovery, gateway) in progress._ +### Fixed (Jira OAuth callback in the dev profile — `bugfix/jira-dev-callback-url`) + +- **The `dev` profile pointed the Atlassian callback at `/integrations/jira/callback`, a route the web + does not have.** The web callback lives at `/settings/integrations/jira/callback`, which is what the + base config, `.env.example` and `docs/JIRA_INTEGRATION.md` use. A local "Conectar con Atlassian" without + `JIRA_OAUTH_CALLBACK_URL` sent Atlassian a redirect that did not match the registered one. Production + was not affected: it derives the URL from `FRONTEND_URL`. + ### Added (Story approval — `feature/discovery-story-approval`) - **A story can now be approved, rejected or sent back to draft.** Until now every story stayed in diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index fd4c0398..cf246cce 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -35,7 +35,7 @@ reqsai: oauth: client-id: ${JIRA_OAUTH_CLIENT_ID:dev-client-id} client-secret: ${JIRA_OAUTH_CLIENT_SECRET:dev-client-secret} - redirect-uri: ${JIRA_OAUTH_CALLBACK_URL:http://localhost:4200/integrations/jira/callback} + redirect-uri: ${JIRA_OAUTH_CALLBACK_URL:http://localhost:4200/settings/integrations/jira/callback} state-secret: ${JIRA_OAUTH_STATE_SECRET:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef} logging: From 052eabf4c6ed39216ac9508ba002919459d9eb6c Mon Sep 17 00:00:00 2001 From: Gutierrez Soto Jhosepmyr Orlando Date: Thu, 8 Oct 2026 15:17:27 -0500 Subject: [PATCH 3/3] docs(billing): describe the current reqsai.tech deployment and the real plan prices BILLING.md pointed the Stripe webhook at app.tamci.app behind CloudFront/ALB, a layout the MVP no longer uses: Caddy serves the web and proxies /api/* on reqsai.tech, so the webhook is https://reqsai.tech/api/billing/webhooks/stripe. It also asked for USD 29/99 prices while the app displays and charges 49/149. --- CHANGELOG.md | 10 ++++++++++ docs/BILLING.md | 24 +++++++++++------------- src/main/resources/application.yml | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bbe7908..eb60cc5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,16 @@ follows [Semantic Versioning](https://semver.org/). _Bounded-context implementation (iam, billing, workspace, discovery, gateway) in progress._ +### Fixed (Billing guide matches the current deployment — `bugfix/docs-billing-current-deploy`) + +- **`docs/BILLING.md` described an old AWS layout**, with CloudFront, an ALB and the `app.tamci.app` + domain. The MVP now runs on `reqsai.tech`, where Caddy serves the web and proxies `/api/*` from one + origin, so the Stripe webhook is `https://reqsai.tech/api/billing/webhooks/stripe`. +- **The guide now says where the MVP host keeps the Stripe settings:** the infra vault and + `app_api_settings`. +- **The Stripe prices to create are USD 49 (Pro) and USD 149 (Enterprise)**, the amounts the app + displays (`BILLING_*_AMOUNT_CENTS`). The guide said USD 29 and USD 99. + ### Fixed (Jira OAuth callback in the dev profile — `bugfix/jira-dev-callback-url`) - **The `dev` profile pointed the Atlassian callback at `/integrations/jira/callback`, a route the web diff --git a/docs/BILLING.md b/docs/BILLING.md index 461a0555..d08c7f8c 100644 --- a/docs/BILLING.md +++ b/docs/BILLING.md @@ -35,12 +35,12 @@ Create the plans in Stripe to map them to your system: 2. Create **"ReqsAI Pro"**: - Pricing: **Recurring** - Interval: **Monthly** - - Amount: **USD 29.00** + - Amount: **USD 49.00** - Save the product and copy the **Price ID** (looks like `price_1AbPro...`). 3. Create **"ReqsAI Enterprise"**: - Pricing: **Recurring** - Interval: **Monthly** - - Amount: **USD 99.00** + - Amount: **USD 149.00** - Save and copy the **Price ID** (looks like `price_1AbEnt...`). 4. Set these in your `.env` file: ```env @@ -108,23 +108,22 @@ For university presentations, demo environments, or staging deployments, **you s Since your deployed application has a public domain name, **you do not need the Stripe CLI (`stripe listen`) running on your server**. Stripe can send the webhook events directly to your public URL: 1. In the Stripe Dashboard (with **Test Mode** turned ON), go to **Developers** ▸ **Webhooks** and click **Add endpoint**. -2. Set the **Endpoint URL** to your deployed **frontend** domain, not the bare API domain: +2. Set the **Endpoint URL** to the public domain of the app. The web and the API share one origin + (Caddy proxies `/api/*` to the API on the MVP host), so the webhook lives under the same domain: ```text - https://app.tamci.app/api/billing/webhooks/stripe + https://reqsai.tech/api/billing/webhooks/stripe ``` - > [!WARNING] - > `api.tamci.app` resolves directly to the ALB, which is locked down to CloudFront-only ingress - > (see [reqsai-infra](https://github.com/Kntro-Soft/reqsai-infra)'s security groups). Stripe's - > servers are not CloudFront, so a webhook pointed at `api.tamci.app` times out silently — no - > log entry on the backend at all, since the request never reaches it. Always use - > `app.tamci.app` (routed through CloudFront) for anything Stripe needs to reach. 3. Click **Select events** and subscribe to: * `checkout.session.completed` * `customer.subscription.deleted` * `invoice.payment_failed` 4. Click **Add endpoint** to save. 5. Under the endpoint details page, click **Reveal** under the **Signing secret** section. -6. Copy this secret (starts with `whsec_...`) and configure the `STRIPE_WEBHOOK_SECRET` environment variable on your deployed server (e.g., in AWS, Render, or ECS). +6. Copy this secret (starts with `whsec_...`) into the deployment's secrets. On the MVP host it is + `vault_stripe_webhook_secret` in the ansible vault of + [reqsai-infra](https://github.com/Kntro-Soft/reqsai-infra), next to `vault_stripe_api_key`. The + provider and the price ids go in the host's `app_api_settings` (`BILLING_PAYMENT_PROVIDER: stripe`, + `BILLING_*_STRIPE_PRICE_ID`). Redeploy so the API picks them up. --- @@ -138,8 +137,7 @@ When deploying to production, apply the following changes: 2. **Products & Prices**: Create the production products and prices in the live dashboard catalog and update `BILLING_*_STRIPE_PRICE_ID` environment variables. 3. **Webhook Registration**: - Go to **Developers** ▸ **Webhooks** ▸ **Add endpoint**. - - Set the URL to `https://app.tamci.app/api/billing/webhooks/stripe` — **not** `api.tamci.app` - (see the warning above: the bare API domain is CloudFront-only and unreachable from Stripe). + - Set the URL to `https://reqsai.tech/api/billing/webhooks/stripe` (same origin as the web app). - Subscribe to these events: * `checkout.session.completed` (handles purchase / upgrade activation). * `customer.subscription.deleted` (handles cancellation/lapse). diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b776593b..58598272 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -143,7 +143,7 @@ reqsai: # ISO-4217 display currency. currency: ${BILLING_CURRENCY:USD} # Per-plan DISPLAY pricing (minor units / cents) + the Stripe Price id actually charged. - # Defined prices: PRO USD 29.00/mo, ENTERPRISE USD 99.00/mo (FREE is $0, provisioned on signup). + # Defined prices: PRO USD 49.00/mo, ENTERPRISE USD 149.00/mo (FREE is $0, provisioned on signup). # NOTE: amount-cents is display only; the CHARGED amount is the Stripe Price object, so the # recurring Price you create in Stripe MUST match these amounts (keep the web plan catalog in sync). plans: