Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
22135ae
feat: expose member display-name lookup on workspace::api
jhosepmyr Jul 7, 2026
bec1070
feat: stash authenticated orgId in STOMP session attributes
jhosepmyr Jul 7, 2026
1f0f891
feat: add PRESENCE_STATE session realtime message contract
jhosepmyr Jul 7, 2026
fd0d5e5
feat: track live discovery-session presence over STOMP
jhosepmyr Jul 7, 2026
55377cd
test: cover session presence registry transitions
jhosepmyr Jul 7, 2026
e95b0b6
docs: document live session presence
jhosepmyr Jul 7, 2026
4a14bb9
test: cover presence resolver caching and STOMP tracker broadcasts
jhosepmyr Jul 7, 2026
08183c6
fix: stash authenticated userId in STOMP session attributes too
jhosepmyr Jul 8, 2026
b03a7df
fix: read presence identity from session attributes, not Principal
jhosepmyr Jul 8, 2026
1a2177c
docs: correct STOMP Principal persistence claim in REALTIME.md
jhosepmyr Jul 8, 2026
6483519
fix: annotate SessionPresenceMessage.type() with @JsonProperty
jhosepmyr Jul 8, 2026
e5ed2de
test: guard every SessionRealtimeMessage's JSON type field
jhosepmyr Jul 8, 2026
b75d24f
fix: filter realtime integration tests by expected event type
jhosepmyr Jul 10, 2026
f023a3c
Merge pull request #56 from Kntro-Soft/feature/discovery-presence
jhosepmyr Jul 10, 2026
94515bc
fix: point APP_URL/FRONTEND_URL/CORS at the custom domain (tamci.app)
jhosepmyr Jul 10, 2026
4369d90
Merge pull request #59 from Kntro-Soft/hotfix/sync-domain-urls-develop
jhosepmyr Jul 10, 2026
51471d7
docs(adr): add ADR-0022 for extensible third-party integrations (jira)
jhosepmyr Jul 6, 2026
f533dea
feat(integrations): add V21 tenant migration for connections and proj…
jhosepmyr Jul 7, 2026
5628632
feat(discovery): expose story read port via discovery::api and add in…
jhosepmyr Jul 7, 2026
c333985
feat(integrations): add module + aes-256-gcm secret encryption at rest
jhosepmyr Jul 7, 2026
1fe8096
feat(integrations): add domain aggregates, jira restclient adapter an…
jhosepmyr Jul 7, 2026
3af9ac3
feat(integrations): add cqrs commands, queries and handlers for conne…
jhosepmyr Jul 7, 2026
efa3b23
feat(integrations): add rest endpoints for jira connections, targets …
jhosepmyr Jul 7, 2026
15d88e0
test(integrations): cover encryption, adf builder, handlers and jira …
jhosepmyr Jul 7, 2026
f86d3ab
fix: set MAIL_FROM from the SMTP secret's username
jhosepmyr Jul 10, 2026
631209a
docs(changelog): note the integrations jira bounded context and endpo…
jhosepmyr Jul 7, 2026
a54e2f1
refactor(integrations): put secret encryption behind a SecretCipher p…
jhosepmyr Jul 7, 2026
ca7c527
refactor(gateway): relocate the jira integration into the reserved ga…
jhosepmyr Jul 7, 2026
ca7112b
refactor(gateway): split integration tenant migration into V21 connec…
jhosepmyr Jul 7, 2026
1cfb046
feat(gateway): add oauth2 credential type to integration connections
jhosepmyr Jul 7, 2026
e932df4
feat(gateway): add jira oauth error codes and optional oauth config
jhosepmyr Jul 7, 2026
60f7e44
feat(gateway): dual-mode jira client with oauth token refresh
jhosepmyr Jul 7, 2026
06998e5
feat(gateway): add jira oauth authorize-url and callback endpoints
jhosepmyr Jul 7, 2026
25ec4fd
chore(scripts): add oauth state secret generator
jhosepmyr Jul 7, 2026
4cc5ca9
fix(gateway): cache oauth tokens across the two-step multi-site callback
jhosepmyr Jul 7, 2026
afd10d8
test(gateway): cover jira oauth state, callback, refresh and dual-mod…
jhosepmyr Jul 7, 2026
49fd52f
docs(gateway): document jira oauth 2.0 3lo in adr-0022 and changelog
jhosepmyr Jul 7, 2026
7d4a5c1
test(gateway): align oauth integration test org slug with its schema
jhosepmyr Jul 7, 2026
bc9e72c
docs(env): document integrations encryption key and jira oauth vars i…
jhosepmyr Jul 7, 2026
d2e5f84
chore(scripts): add integrations encryption key generator
jhosepmyr Jul 7, 2026
7adfb9b
docs(gateway): add jira integration setup guide (scopes, callback, se…
jhosepmyr Jul 7, 2026
5cdb8e7
feat(workspace): let org admins view organization general settings
jhosepmyr Jul 7, 2026
c708105
fix(gateway): create Jira issues by project issue-type id and surface…
jhosepmyr Jul 7, 2026
ee07f0b
feat(discovery): add discovery::api write port to import external iss…
jhosepmyr Jul 7, 2026
1b3eada
fix(discovery): isolate external-issue import per transaction with pr…
jhosepmyr Jul 7, 2026
4831173
feat(gateway): add import contracts to the integration provider port
jhosepmyr Jul 7, 2026
8fdc634
feat(gateway): fetch and map importable Jira issues
jhosepmyr Jul 7, 2026
1ba9a52
feat(gateway): import Jira issues as stories via the discovery write …
jhosepmyr Jul 7, 2026
ef4244a
feat(gateway): expose Jira import preview and import endpoints
jhosepmyr Jul 7, 2026
f213c20
test(gateway): cover Jira import preview, batch and issue mapping
jhosepmyr Jul 7, 2026
9266021
test(discovery): drop unnecessary highestSimilarity stub
jhosepmyr Jul 8, 2026
9d5ee8d
refactor(gateway): rename integration migrations to timestamp versions
jhosepmyr Jul 8, 2026
94796ca
docs(gateway): renumber Jira integrations ADR references to 0023
jhosepmyr Jul 8, 2026
5ccf1b5
fix(discovery): skip the llm in the import duplicate pre-check
jhosepmyr Jul 10, 2026
9b9611f
fix(gateway): stop double-encoding the jira search jql uri
jhosepmyr Jul 10, 2026
edb62af
feat(gateway): fill required jira custom fields on issue create
jhosepmyr Jul 10, 2026
678054d
feat(gateway): add durable integration sync job aggregate
jhosepmyr Jul 10, 2026
01a5085
feat(gateway): run jira sync jobs on a tenant-aware async worker
jhosepmyr Jul 10, 2026
be9d268
feat(shared): persist spring batch metadata in the public schema
jhosepmyr Jul 10, 2026
93979ec
refactor(gateway): drive jira sync jobs through spring batch
jhosepmyr Jul 10, 2026
86035d1
feat(gateway): switch jira import and push-all to async 202 job endpo…
jhosepmyr Jul 10, 2026
890fd55
test(gateway): cover sync job domain, starter guard and batch listeners
jhosepmyr Jul 10, 2026
40a1bcb
docs: document the async jira sync jobs and spring batch decision
jhosepmyr Jul 10, 2026
536b15c
feat(workspace): add STORY_DELETE permission to the catalog
jhosepmyr Jul 10, 2026
bb67553
feat(discovery): add user-story delete and batch-delete commands
jhosepmyr Jul 10, 2026
2800a3d
feat(discovery): expose story delete and batch-delete endpoints
jhosepmyr Jul 10, 2026
66db1c7
feat(gateway): let Jira push-all target an optional story selection
jhosepmyr Jul 10, 2026
1e5334e
Merge pull request #62 from Kntro-Soft/hotfix/sync-smtp-from-develop
jhosepmyr Jul 10, 2026
0f20ea0
fix: block /api/auth/dev-token outside the dev profile
jhosepmyr Jul 10, 2026
844fda3
test(discovery): discriminate realtime frames by their wire type
jhosepmyr Jul 10, 2026
9ce14fa
Merge pull request #48 from Kntro-Soft/feature/integrations-jira
jhosepmyr Jul 10, 2026
0685deb
fix: stop exposing metrics/modulith/info actuator endpoints over HTTP
jhosepmyr Jul 10, 2026
46eae8e
Merge pull request #63 from Kntro-Soft/bugfix/restrict-dev-token-endp…
jhosepmyr Jul 10, 2026
fba1965
feat: wire Jira OAuth config into the ECS task definition
jhosepmyr Jul 10, 2026
bf3247d
Merge pull request #65 from Kntro-Soft/feature/jira-integration-secrets
jhosepmyr Jul 10, 2026
6b2245a
feat: default Jira OAuth callback URL to FRONTEND_URL
jhosepmyr Jul 10, 2026
0c45c99
Merge pull request #67 from Kntro-Soft/bugfix/jira-callback-url-default
jhosepmyr Jul 10, 2026
a05b01d
feat: wire Stripe billing config into the ECS task definition
jhosepmyr Jul 10, 2026
11d1ebc
Merge pull request #68 from Kntro-Soft/feature/stripe-billing-secrets
jhosepmyr Jul 10, 2026
282dc84
docs: document Stripe billing and Jira callback default in CHANGELOG
jhosepmyr Jul 10, 2026
c77a74a
Merge pull request #70 from Kntro-Soft/feature/changelog-billing-jira…
jhosepmyr Jul 10, 2026
cfcb5f4
Merge remote-tracking branch 'origin/main' into bugfix/resolve-task-d…
jhosepmyr Jul 10, 2026
05294d1
Merge pull request #72 from Kntro-Soft/bugfix/resolve-task-definition…
jhosepmyr Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,12 @@ JWT_ISSUER=reqsai
# Optional: Override display amounts in cents (must match Stripe Price object)
# BILLING_PRO_AMOUNT_CENTS=2900
# BILLING_ENTERPRISE_AMOUNT_CENTS=9900

# ── Integrations — Jira (gateway) ─────────────────────────────────────────────
# INTEGRATIONS_ENCRYPTION_KEY=your-base64-32-byte-key-here
# JIRA_OAUTH_CALLBACK_URL must match the app's Authorization → Callback URL exactly.
# Defaults to {FRONTEND_URL}/settings/integrations/jira/callback — only set this to override.
# JIRA_OAUTH_CLIENT_ID=your-atlassian-oauth-client-id
# JIRA_OAUTH_CLIENT_SECRET=your-atlassian-oauth-client-secret
# JIRA_OAUTH_CALLBACK_URL=http://localhost:4200/settings/integrations/jira/callback
# JIRA_OAUTH_STATE_SECRET=your-hex-64-char-state-secret
154 changes: 154 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,160 @@ follows [Semantic Versioning](https://semver.org/).

_Bounded-context implementation (iam, billing, workspace, discovery, gateway) in progress._

### Added (Billing / Stripe subscriptions — `feature/billing-subscription-payments-quota`)

- **Paid subscription lifecycle** — the `Subscription` aggregate gains upgrade/cancel/reactivate/downgrade
transitions plus AI token-quota accounting with automatic period rollover, driven by new lifecycle
domain events. `PlanCatalog` defines PRO/ENTERPRISE limits; pricing is config-driven via
`BillingProperties` (`reqsai.billing.*`, display amounts in minor units + currency) — currently PRO
USD 49.00/mo and ENTERPRISE USD 149.00/mo, matching the marketing landing page.
New REST endpoints on the subscription controller: `PUT .../upgrade`, `PUT .../cancel`,
`PUT .../reactivate`, `GET .../usage`.
- **AI token metering** — `BillingModuleApi.recordTokenConsumption`/`hasTokenQuotaAvailable`/`planLimits`
let Discovery capture provider-reported token usage from each LLM response and meter it against the
tenant's subscription quota (best-effort — a metering failure never breaks generation).
- **Stripe as a real payment gateway** (`PaymentGatewayPort`, swapped in by
`reqsai.billing.payment-provider=stripe`; `fake` — synchronous plan activation, no charge — stays the
default) implemented over Spring `RestClient` + a hand-rolled HMAC verifier, no Stripe SDK, to keep the
dependency surface minimal:
- `StripePaymentGatewayAdapter` creates a hosted Checkout Session (subscription mode) and returns its
URL; the plan is only activated from the webhook, honoring the same `PlanChangeResult` contract as
the fake gateway so domain/handlers are unchanged. Checkout return URLs derive from `WEB_APP_URL`
(`.../billing/success`, `.../billing/cancel`) rather than the API host.
- `StripeWebhookParser` verifies the `Stripe-Signature` header (HMAC-SHA256 over
`<timestamp>.<payload>`) and maps events to a gateway-agnostic `PaymentWebhookEvent`.
- `ProcessPaymentWebhookCommandHandler` de-duplicates by event id (new `public.billing_processed_events`,
common migration `V13__billing_processed_events.sql`) and applies plan activation / downgrade /
past-due. New endpoint `POST /api/billing/webhooks/stripe` (signature-verified, JWT-exempt in
`SecurityConfiguration`).
- **Cross-module relay** — on upgrade/downgrade, Billing publishes a
`SubscriptionPlanChangedIntegrationEvent` on `billing::api`; Workspace mirrors the new plan limits onto
its `Organization` aggregate.
- **Docs** — [docs/BILLING.md](docs/BILLING.md) covers Stripe test-mode setup, product/price
configuration, local webhook forwarding via the Stripe CLI, and deployed-environment webhooks;
`.env.example` documents every billing/Stripe variable (provider flag, API key, per-plan Price ids,
webhook secret, return-URL overrides).

### Added (Live session presence — `feature/discovery-presence`)

- **Real-time presence for live discovery sessions** — the users currently viewing a live session are
now tracked and broadcast so every participant sees who else is present. A new `PRESENCE_STATE`
event on the existing per-session topic (`/topic/sessions/{id}`) carries a `SessionPresenceMessage`
snapshot: the full participant list (`userId`, `displayName`, `avatarUrl`) plus a distinct `count`.
Presence is driven entirely by STOMP lifecycle events — subscribing to the session topic **is** the
presence signal; unsubscribe/disconnect removes the user; the same user across two tabs counts once.
- **`WorkspaceModuleApi.findMemberDisplayName(orgId, userId)`** — new read on the `workspace::api` ACL
so discovery labels participants from the member roster (`public.members`) without reaching into
workspace internals; the result is Caffeine-cached per tenant+user.
- **No Redis / no schema change** — the presence roster is ephemeral in-process state (a
`SessionPresenceRegistry` alongside the in-memory broker). Like the `SIMPLE` broker (ADR-0007) it is
per-JVM; a fully global roster across multiple instances would require the shared `RELAY` broker's
state. The authenticated `orgId` is stashed in the STOMP session attributes on CONNECT so the
broker-thread listeners can resolve the tenant.

### Added (Integrations / Jira — `feature/integrations-jira`)

- **Jira Cloud integration in the reserved `gateway` bounded context** (ADR-0023) — the feature reuses
the `com.kntro.reqsai.gateway` module reserved for external integrations. Extensible
provider model (`IntegrationProvider` port + `JiraProvider`) whose credentials live at the
**organization** level and whose push target lives at the **project** level.
- **Org connection endpoints** (org owner/admin gated): `GET /organizations/{orgId}/integrations`,
`POST /organizations/{orgId}/integrations/jira` (`{siteUrl,email,apiToken}` — verifies against Jira
then stores the token **encrypted**; `409 INTEGRATION_ALREADY_CONNECTED` when one already exists),
`POST /organizations/{orgId}/integrations/{connectionId}/test` (`{ok, accountName?}`),
`DELETE /organizations/{orgId}/integrations/{connectionId}` (`204`),
`GET /organizations/{orgId}/integrations/{connectionId}/jira/projects`,
`GET /organizations/{orgId}/integrations/{connectionId}/jira/issue-types?projectKey=`.
The API token is **never** returned by any response.
- **Project target + push endpoints** (project `INTEGRATION_*` gated):
`GET/PUT/DELETE /projects/{projectId}/integration/jira/target` (single target per project;
`404` when none), `POST /projects/{projectId}/integration/jira/stories/{storyId}/push`
(`{storyId,jiraIssueKey,jiraIssueUrl}`; `409 INTEGRATION_TARGET_NOT_CONFIGURED` when no target),
`POST /projects/{projectId}/integration/jira/stories/push-all` (now an **async job** — see the
"async sync jobs" entry below). All endpoints use header `Api-Version: 1`.
- **Encryption at rest** — AES-256-GCM `AttributeConverter` (random 12-byte IV prepended to the
ciphertext) keyed from `INTEGRATIONS_ENCRYPTION_KEY` (base64 32 bytes); a documented default key is
provided for dev/test so the suite runs without a `.env`.
- **RBAC** — new project permissions `INTEGRATION_READ`, `INTEGRATION_WRITE`, `INTEGRATION_DELETE`,
`INTEGRATION_SYNC` added to the workspace `Permission` catalog. IAM identity/auth is unchanged.
- **Cross-module read** — discovery now publishes a `discovery::api` named interface
(`DiscoveryStoryReadPort` returning value-only `StoryView`s) so the `gateway` module can read user stories
(title/role/action/benefit/priority/story points + Given/When/Then) to render the Jira issue
description as ADF. The story is pushed with the `EXPORTED`-style export flow.
- Migration `V20260708055818__integration_connections.sql` (tenant schema): `integration_connections`
(org-scoped, one active per org+provider) and `project_integration_targets` (project-scoped, one
per project). New error codes: `INTEGRATION_CONNECTION_NOT_FOUND`, `INTEGRATION_ALREADY_CONNECTED`,
`INTEGRATION_TARGET_NOT_CONFIGURED`, `JIRA_PROJECT_NOT_FOUND`, `JIRA_AUTH_FAILED`,
`JIRA_UNREACHABLE`, `JIRA_PUSH_FAILED`, `INTEGRATION_ENCRYPTION_ERROR`.
- **Jira OAuth 2.0 (3LO) as a second credential type** (ADR-0023) — added alongside the API-token
flow, which is unchanged. A `credentialType` (`API_TOKEN` | `OAUTH2`) selects the auth: OAuth uses
bearer auth against `https://api.atlassian.com/ex/jira/{cloudId}/rest/api/3`, API tokens keep basic
auth against `https://{site}/rest/api/3`. **`IntegrationConnectionResponse` now carries
`credentialType`, and `email` is `null` for `OAUTH2` connections** (frontend contract change). No
token or ciphertext is ever returned.
- **New org-admin-gated endpoints** (header `Api-Version: 1`):
`GET /organizations/{orgId}/integrations/jira/oauth/authorize-url` → `{url, state}` (the `state`
is a stateless HMAC-signed token over org+user+expiry+nonce; `501 JIRA_OAUTH_NOT_CONFIGURED` when
OAuth is unconfigured), and
`POST /organizations/{orgId}/integrations/jira/oauth/callback` `{code, state, cloudId?}` — validates
the state, exchanges the code, and either saves an encrypted `OAUTH2` connection (cloudId given or
exactly one accessible site) or returns `200 {sites:[…]}` to choose from (multiple sites), enforcing
the one-active-connection rule (`409 INTEGRATION_ALREADY_CONNECTED`). Authorization codes are
single-use, so the exchanged tokens are cached under the `state` (short TTL) and the site-selection
re-POST completes from the cache without re-exchanging the code.
- **Token handling** — OAuth refresh + access tokens are encrypted at rest with the same AES-256-GCM
`SecretCipher`; before an OAuth call the access token is refreshed if near expiry and the **rotated**
refresh token is persisted (`JIRA_AUTH_FAILED` on refresh failure).
- **Config** (all optional; the app boots when unset): `reqsai.integrations.jira.oauth.client-id`,
`client-secret`, `redirect-uri` (from `JIRA_OAUTH_CLIENT_ID` / `JIRA_OAUTH_CLIENT_SECRET` /
`JIRA_OAUTH_CALLBACK_URL`, defaulting to `${FRONTEND_URL}/settings/integrations/jira/callback` when
unset — matching the `WEB_APP_URL`-derived pattern used by Stripe's checkout return URLs) and a
dedicated `state-secret` (`JIRA_OAUTH_STATE_SECRET`; generate with
`scripts/generate-oauth-state-secret.sh`).
- Migration `V20260708055820__integration_connections_oauth.sql` (tenant, additive): adds `credential_type`
(default `API_TOKEN`), `cloud_id`, `oauth_refresh_ciphertext`, `oauth_access_ciphertext`,
`oauth_access_expires_at`, and relaxes `email` + `secret_ciphertext` to nullable. New error codes:
`JIRA_OAUTH_NOT_CONFIGURED` (501), `JIRA_OAUTH_STATE_INVALID` (400),
`JIRA_OAUTH_EXCHANGE_FAILED` (502).

### Added (Integrations / Jira — async sync jobs on Spring Batch, `feature/integrations-jira`)

- **Jira import and push-all now run as background jobs** (ADR-0023). The blocking requests (minutes of
LLM transformations / issue creation) are gone:
- `POST /projects/{projectId}/integration/jira/import` (`{issueKeys?}`) and
`POST /projects/{projectId}/integration/jira/stories/push-all` now answer **`202 Accepted`** with an
`IntegrationJobResponse` snapshot `{id, projectId, jobType: IMPORT|PUSH_ALL, status:
RUNNING|COMPLETED|FAILED, total, processed, succeeded, failed, message, createdAt, finishedAt}`.
`409 INTEGRATION_JOB_ALREADY_RUNNING` when a job of the same type is already RUNNING for the project
(at most one, enforced by a partial unique index). The single-story push and the import preview stay
synchronous.
- **Live progress over STOMP** — every per-item update and the terminal state are broadcast as the full
`IntegrationJobResponse` JSON on **`/topic/projects/{projectId}/integration-jobs`** (JWT-authenticated
CONNECT, as with the other project topics).
- **Reload recovery** — `GET /projects/{projectId}/integration/jira/jobs?active=true` returns the
RUNNING jobs (re-attach the progress banner after a reload); without the flag the most recent ~10 of
any status. `GET .../jobs/{jobId}` returns one job (`404 INTEGRATION_JOB_NOT_FOUND`). Job reads are
gated by `INTEGRATION_READ`; job starts keep `INTEGRATION_SYNC`.
- **Durable state** — new tenant migration `V20260709100000__integration_sync_jobs.sql`
(`integration_sync_jobs`, the domain-facing projection and source of truth for the UI). Import
duplicates count toward `processed` only; the terminal message summarizes them
("N duplicados omitidos"). A fatal error (e.g. Jira unreachable) marks the job `FAILED` with a message.
- **Engine: Spring Batch 6** — two chunk-oriented jobs (`jiraImportJob`, `jiraPushAllJob`; chunk size 5,
per-item skip policy so one bad item never aborts the run) behind the application-layer
`IntegrationJobLauncher` port. Batch metadata (`BATCH_JOB_INSTANCE`, `BATCH_JOB_EXECUTION`, ...) lives
in the **global `public` schema** (common migration `V20260709100001__spring_batch_metadata.sql`) with
the JobRepository schema-qualified via table prefix `public.BATCH_` — immune to the per-tenant
`search_path` routing. The caller's tenant is captured into job parameters and restored around the
execution. `spring.batch.job.enabled=false` (jobs run only on API demand).

### Changed (Workspace — `feature/integrations-jira`)

- **Org admins may now view organization general settings** — `GET /organizations/{orgId}` is now gated
by `@authz.orgOwnerOrAdmin` instead of `@authz.orgOwner`, so an organization **admin** receives `200`
when reading the org (previously `403`). Editing stays owner-only: `PATCH /organizations/{orgId}`,
`POST /organizations/{orgId}/transfer-ownership`, and `DELETE /organizations/{orgId}` remain
`@authz.orgOwner`. Non-members still receive `403` on the GET.

### Added (Backlog / Glossary / Constraints listing — `feature/discovery-session-control`)

- **User-story backlog list filters + search** — `GET /projects/{projectId}/stories` now accepts five
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Detalle en [`docs/DEPLOYMENT.md`](./docs/DEPLOYMENT.md).
| [`docs/LOCAL_AI.md`](./docs/LOCAL_AI.md) | IA local↔nube (LLM, embeddings, STT) — Mac/Win/Linux |
| [`docs/DEPLOYMENT.md`](./docs/DEPLOYMENT.md) | Despliegue (Docker, AWS ECS Fargate, CI/CD) |
| [`docs/MIGRATIONS.md`](./docs/MIGRATIONS.md) | Cómo crear migraciones Flyway (`scripts/new-migration.sh`) |
| [`docs/JIRA_INTEGRATION.md`](./docs/JIRA_INTEGRATION.md) | Integración Jira: permisos, callback, secretos, uso |
| [`.github/CONTRIBUTING.md`](./.github/CONTRIBUTING.md) | Flujo de trabajo, build, tests, ramas, commits |
| [`CHANGELOG.md`](./CHANGELOG.md) | Historial de cambios (Keep a Changelog) |
| [`AUTHORS.md`](./AUTHORS.md) · [`CONTRIBUTORS.md`](./CONTRIBUTORS.md) · [`ACKNOWLEDGMENTS.md`](./ACKNOWLEDGMENTS.md) | Equipo y créditos |
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dependencies {
// DATA + DB
// ==================================
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-batch")
implementation("org.springframework.boot:spring-boot-starter-flyway")
implementation("org.flywaydb:flyway-database-postgresql")
implementation("org.hibernate.orm:hibernate-vector")
Expand Down
Loading
Loading