Commit Graph
17462 Commits
Author SHA1 Message Date
Jake BarnbyandClaude Opus 4.7 83c0a32494 fix(advisor): make reports.target a TEXT column
target stores free-form URLs or resource IDs. URLs in the wild can
exceed the prior 2048-char cap, so switch the column to VAR_TEXT
(65535). The _key_project_target index already declares an explicit
700-char prefix length, so indexing still works on both MariaDB and
MongoDB.

Bump APP_CACHE_BUSTER for the schema change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:42:29 +12:00
Jake BarnbyandClaude Opus 4.7 b830c08257 fix(advisor): use VAR_TEXT for free-form fields
Switch markdown summaries, JSON CTA params, and the embedded
insights/ctas subQuery payloads from sized VAR_STRING to VAR_TEXT.
None of these fields are indexed and they all hold free-form data, so
removing the artificial size cap means we never have to revisit the
limit when an analyzer surfaces a longer report.

- reports.summary, insights.summary: markdown, no upper bound enforced
- reports.insights, insights.ctas: subQuery virtuals carrying full
  child rows
- insightCTAs.params: JSON parameter blob for arbitrary CTA actions

Bump APP_CACHE_BUSTER for the schema change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:30:45 +12:00
Jake BarnbyandClaude Opus 4.7 b747c97561 fix(advisor): address review comments on scopes and schema
- Register dedicated reports.write scope and switch deleteReport to it
  so cloud can issue narrowly-scoped delete keys without granting
  insights.write.
- Make insights.parentResourceInternalId optional with null default to
  match its companion parentResourceType/parentResourceId fields and
  unblock insights with no parent (e.g. database-level performance
  insights).
- Tighten Insight.reportId model description: insights always belong to
  a report, ad-hoc insights are not supported.
- Add reports.write to default test API key and admin role so existing
  e2e tests using serverHeaders() can hit the delete endpoint.
- Bump APP_CACHE_BUSTER for the schema change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:18:39 +12:00
copilot-swe-agent[bot]andabnegate 6b64eb85b3 fix(advisor): require null-default VAR_ID schema fields
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/38cebef5-ed45-4283-9097-d48dd0fafb06

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-09 00:00:28 +00:00
Jake BarnbyandClaude Opus 4.7 83cf47e3fd fix(advisor): correct index lengths to fit MongoDB 1024 limit
The reports `_key_project_target` index was failing to create on MongoDB
because target's full size (2048) plus targetType (64) exceeded the 1024
character maximum. Set explicit lengths to truncate target to 700 chars
(total 765, under both Mongo 1024 and MariaDB 768 limits).

Also drop redundant explicit lengths from VAR_ID positions in the
insights and insightCTAs indexes — the validator rejects explicit
lengths on VAR_ID attributes, and they default to length 1 anyway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:29:01 +12:00
Abhay 27de465032 Merge branch '1.9.x' into fix/scheduler-platform-env 2026-05-08 17:14:42 +05:30
Aditya Oberai 8df7a628c8 Merge branch '1.9.x' into add-codex-plugin 2026-05-08 09:34:43 +00:00
Chirag Aggarwal 34075322d7 Migrate mails and messaging queues to publishers 2026-05-08 14:32:11 +05:30
copilot-swe-agent[bot]andabnegate 56b9de097f fix(advisor): restore report delete with async nested cleanup
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/6496395d-5cbf-42ba-a3e0-d3c9e6ca901c

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 06:54:49 +00:00
Jake Barnby 602e1be296 Merge pull request #12226 from appwrite/spike/isPublishable-migration
Stop user-data errors leaking to Sentry from migrations worker (isPublishable)
2026-05-08 18:22:41 +12:00
copilot-swe-agent[bot]andabnegate a9902c33df chore(advisor): clarify insights.write scope usage
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/8d7897b5-ac68-487d-954a-be717380bf66

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 06:08:17 +00:00
copilot-swe-agent[bot]andabnegate 6d0eab2583 refactor(advisor): make insights API read-only in CE
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/8d7897b5-ac68-487d-954a-be717380bf66

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 06:07:23 +00:00
Chirag Aggarwal 8ebf4fee46 Use storage cache callback max age 2026-05-08 11:18:55 +05:30
Chirag Aggarwal 9337daf7ac Preserve default storage cache hit max age 2026-05-08 11:15:17 +05:30
copilot-swe-agent[bot]andabnegate 0829b26508 refactor(insights): remove redundant payload field
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/a680e208-34b8-4bae-a7fd-51949112233a

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 05:44:20 +00:00
copilot-swe-agent[bot]andabnegate 8c57ff161e fix(insights): use VAR_ID for project internal references
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/688345d8-e680-46c7-9002-82f73193461b

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 05:17:15 +00:00
copilot-swe-agent[bot]andabnegate 0d65ffbb6c chore(insights): simplify report index lengths and orders
Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/2e52811c-bf98-4b39-b3f7-64fabcef4cf6

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
2026-05-08 05:13:38 +00:00
Chirag Aggarwal 75a30793ac Remove preview flag from storage cache config 2026-05-08 10:42:39 +05:30
Chirag Aggarwal 5841d0a944 Inline storage preview cache control 2026-05-08 09:59:36 +05:30
Chirag Aggarwal bf76736971 Split storage cache control context 2026-05-08 09:57:33 +05:30
Chirag Aggarwal 707e5d231a Scope storage cache control to previews 2026-05-08 09:55:33 +05:30
Chirag Aggarwal 6abd88b8f1 Type storage cache control config 2026-05-08 09:44:00 +05:30
Chirag Aggarwal 7b5a5b8d19 Rename storage cache control hook 2026-05-08 08:44:35 +05:30
Chirag Aggarwal 20ab5b026e Add cached response cache-control callback 2026-05-08 08:33:37 +05:30
premtsd-code f2b96318ca Merge branch '1.9.x' into spike/isPublishable-migration 2026-05-07 21:37:53 +05:30
Luke B. Silver 1d004240e6 Merge pull request #12236 from appwrite/refactor/builds-publishing
refactor: migrate queueForBuilds to publisherForBuilds pattern
2026-05-07 17:06:32 +01:00
Matej Bačo c3881f9974 Fix console email policy features 2026-05-07 17:13:26 +02:00
loks0nandClaude Opus 4.7 7d0843cc7f Migrate queueForBuilds to publisherForBuilds pattern
Replaces the stateful Appwrite\Event\Build queue class with a stateless
BuildPublisher and BuildMessage DTO, matching the publisher pattern used
by audits, certificates, executions, migrations, screenshots, stats, and
usage. Call sites now enqueue messages directly instead of mutating a
shared event object and relying on the API shutdown hook.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 13:23:21 +01:00
premtsd-code 0b810e500f Merge branch '1.9.x' into spike/isPublishable-migration 2026-05-07 12:42:04 +05:30
loks0n 8201fea9ef Differentiate executor timeouts for builds, sync, and async executions
Adds Executor\Exception\Timeout (with timeoutSeconds) and translates it at
each call site into BUILD_TIMEOUT, FUNCTION_SYNCHRONOUS_TIMEOUT, or
FUNCTION_ASYNCHRONOUS_TIMEOUT instead of always using the misleading sync
function error. Build timeouts now append to streamed buildLogs rather
than replacing them, and the build worker reports its timeout via Span.
2026-05-06 15:54:11 +01:00
Matej Bačo e834a95213 PR review improvements 2026-05-06 16:21:50 +02:00
Matej Bačo d2b551cd12 Fix refreshing nonoauth sessions 2026-05-06 15:50:18 +02:00
Prem Palanisamy f99f2cc1a9 Merge remote-tracking branch 'origin/1.9.x' into spike/isPublishable-migration
# Conflicts:
#	composer.json
#	composer.lock
2026-05-06 13:10:57 +01:00
Prem Palanisamy b094993f77 spike: convert worker throws to AppwriteException + isPublishable gate 2026-05-06 12:34:50 +01:00
Matej Bačo ec927104fe Merge pull request #12221 from appwrite/fix-variables-api-feature-parity
Feat: Variables API feature parity
2026-05-06 11:27:32 +02:00
Jake Barnby 6c6782dd28 Merge remote-tracking branch 'origin/1.9.x' into pr-12194-feat-insights-module
# Conflicts:
#	app/config/scopes/project.php
2026-05-06 20:33:40 +12:00
Matej Bačo 1ccf058c14 Fix failing tests 2026-05-06 10:19:30 +02:00
Jake Barnby 1273bcd33a Merge pull request #11673 from appwrite/big-int
Big int
2026-05-06 20:17:45 +12:00
Matej Bačo add2b7b64a Merge pull request #12208 from appwrite/feat-public-proxy-api
Feat: Public Proxy API
2026-05-06 10:15:57 +02:00
ArnabChatterjee20k a0d77ba1b2 Merge remote-tracking branch 'origin/1.9.x' into big-int 2026-05-06 13:22:37 +05:30
Jake BarnbyandClaude Opus 4.7 68c354e09b refactor(insights): nest insights API under reports
Insights are children of reports — make the URL hierarchy reflect that.

Endpoints:
- POST   /v1/manager/reports/:reportId/insights        (manager Create)
- GET    /v1/reports/:reportId/insights                (List)
- GET    /v1/reports/:reportId/insights/:insightId     (Get)
- PATCH  /v1/reports/:reportId/insights/:insightId     (Update)
- DELETE /v1/reports/:reportId/insights/:insightId     (Delete)

`reportId` moves from optional body field to required path param. All
endpoints fetch the report first (404 REPORT_NOT_FOUND if missing or
in another project), then verify the insight's `reportInternalId`
matches before doing anything else.

Side effects:
- Event names nested: `reports.[reportId].insights.[insightId].create`
  etc. Top-level `insights.*` event tree removed from events.php.
- Realtime channel parser handles the nested form: a `reports.{rid}`
  event lights up `reports`, `reports.{rid}` channels; a nested
  `reports.{rid}.insights.{iid}` event also lights up
  `reports.{rid}.insights` and `reports.{rid}.insights.{iid}`.
- Audit resource paths nested similarly:
  `report/{request.reportId}/insight/{response.$id}`.
- listInsights query validator drops `reportId` from
  ALLOWED_ATTRIBUTES — it's path-scoped now, not a query filter.

Tests:
- E2E helpers `createInsight`/`getInsight`/`listInsights`/
  `updateInsight`/`deleteInsight` all take `reportId` as the first
  argument.
- New `createFixtureReport()` helper for standalone validation tests
  that need a parent.
- Dropped `testCreateWithoutReport` — reportId is mandatory now.
- `testCreateRejectsUnknownReport` now exercises the path-level 404
  rather than a body-level check.
- `testGet` and `testUpdateMissing` exercise the
  wrong-reportId-but-valid-insightId case (returns
  `report_not_found`).
- `testList` asserts every result carries the path's reportId, plus a
  404 case for a nonexistent parent.
- `testCreateForEachEngine` and the standalone create-rejection tests
  inline-create their own fixture report and clean up after.
- `testListSurvivesEmptyDatabase` renamed to
  `testListSurvivesEmptyReport` and uses a fresh fixture report.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:53:54 +12:00
Jake BarnbyandClaude Opus 4.7 0b72dba817 refactor(insights): drop CTA key field
`key` was a leftover from when CTAs were embedded JSON — there's no
remaining reason to require analyzers to invent a within-insight
identifier. The execution layer is gone (no `cta.key` event format),
insights are immutable from the user side (analyzers re-ingest by
delete + recreate, so idempotent matching never happens), and `label`
already covers human-facing identification. The console can group/sort
CTAs by `service`+`method` if needed.

- Schema: drop `key` attribute and the UNIQUE
  `(insightInternalId, key)` index from insightCTAs. Required fields
  are now `label`, `service`, `method` (+ optional `params`).
- Validator no longer requires `key`. Drop the dup-key normalization
  loop in the manager Create endpoint — there's no semantic
  uniqueness to enforce.
- Response model: `InsightCTA` keeps `$id` + standard headers,
  `insightId` backref, and the four functional fields.
- E2E: drop sampleCTA's `$key` parameter, drop the
  testCreateRejectsDuplicateCTAIds test entirely, rename empty-fields
  test to testCreateRejectsCTAWithEmptyLabel and update the missing-
  fields tests to drop `key` from their payloads.
- Unit tests rewritten to drop `key`.
- Comment on the `insights.ctas` virtual attribute updated to
  reference the renamed `insightCTAs` collection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:29:40 +12:00
Jake BarnbyandClaude Opus 4.7 c5dfc42a60 refactor(insights): rename ctas collection to insightCTAs
Disambiguate the platform-level collection name. Field/request-param
remains `ctas` (the embedded array on the insight response).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:12:17 +12:00
Jake BarnbyandClaude Opus 4.7 5404bfec75 refactor(insights): promote CTAs to own collection with backref
Embedding CTAs as a 16384-byte JSON blob on `insights` was the wrong
shape — they're real documents with their own lifecycle. Move them out.

Schema:
- New platform `ctas` collection. Each row carries `projectInternalId`,
  `projectId`, `insightInternalId`, `insightId` (backref), plus the
  CTA fields: `key`, `label`, `service`, `method`, `params`.
- Indexes: `(projectInternalId, insightInternalId)` for the subquery
  lookup and a UNIQUE `(insightInternalId, key)` so the per-insight
  uniqueness invariant lives at the DB layer (not just in PHP).
- The `ctas` field on `insights` becomes a virtual attribute backed by
  a new `subQueryInsightCTAs` filter that joins child docs at read
  time. Consumers still get CTAs embedded on the insight response —
  one round-trip from their perspective.
- The CTA descriptor's within-insight identifier renamed `id` → `key`
  (clashed with the document `$id`). Validator updated.

Endpoints:
- Manager Create now persists CTAs as separate `ctas` documents after
  the parent insight, then re-fetches the insight so the response
  carries the freshly-joined CTA list.
- User Update trimmed to user-controlled state only (`severity`,
  `status`). `title`, `summary`, `payload`, `ctas`, and `analyzedAt`
  are analyzer-controlled — analyzers re-ingest by deleting and
  POSTing again to the manager endpoint.
- Insight Delete cascades to CTAs.
- Report Delete cascades through Insights → CTAs.

Response model:
- InsightCTA gains the standard document headers (`$id`,
  `$createdAt`, `$updatedAt`) and an `insightId` backref. The
  caller-supplied identifier is now `key`.

Tests:
- E2E sampleCTA factory uses `key` everywhere; testCreate asserts the
  freshly-created CTA carries `$id`, `$createdAt`, `insightId`, and
  the right shape.
- Dropped the testUpdate*CTA* tests — user Update no longer accepts
  CTAs. testDismissViaUpdate now depends on testUpdate directly.
- Unit tests rewritten to validate `key` instead of `id`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:07:49 +12:00
Jake BarnbyandClaude Opus 4.7 38efdf18e2 feat(insights): add parent resource pointer
Eldad's review comment: insights about nested resources need a pointer
to the containing parent (the file-in-bucket pattern). Add three
optional fields:

- parentResourceType (plural noun, e.g. `tables`, `collections`)
- parentResourceId
- parentResourceInternalId

so an insight whose `resourceType=indexes` / `resourceId=_idx_status`
can also carry `parentResourceType=tables` / `parentResourceId=orders`
to identify the table that owns the index. All three are nullable for
top-level resources (e.g. a project-wide audit finding).

Schema, response model, manager Create endpoint, and the listInsights
query validator (parent fields are filterable). New compound index
`_key_project_parent_resource(projectInternalId, parentResourceType,
parentResourceId, $sequence)` to support the parent lookup pattern
the console will use ("show all insights for table X").

E2E factory generates a parent by default (engine-aware:
tables for tablesDB, collections for the others). New
testCreateWithoutParentResource exercises the top-level case;
testList gains a parent-resource filter assertion; testUpdate's
preserved-fields check picks up the new attributes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:25:34 +12:00
Jake BarnbyandClaude Opus 4.7 4fc3e9c386 refactor(insights): manager-only Create endpoint + native categories array
Insights are produced by internal Appwrite services (edge, executor,
background analyzers) — never by user clients. Move the ingestion
endpoint accordingly.

- Move Http/Insights/Create.php → Http/Manager/Insights/Create.php.
- Path: /v1/insights → /v1/manager/insights. SDK Method marked
  `hide: true` and namespaced under `manager` so generated SDKs don't
  expose it. Auth narrowed from [ADMIN, KEY] to [KEY] only.
- New scope `insights.manager`. Not granted by any user role
  (app/config/roles.php) — Cloud/edge teams configure their internal
  key issuance to grant it. `insights.write` description trimmed to
  the user-facing surface (update/dismiss/delete) since create is now
  manager-only.
- Reports, ListInsights, GetInsight, UpdateInsight, DeleteInsight
  remain at /v1/insights/*. Existing scopes unchanged.
- Reports `categories` switched from JSON-encoded string to a native
  array<string> column (size 64 per entry, up to 32 entries via the
  endpoint validator). MySQL JSON-array indexes are weak and we never
  query individual entries — read+rewrite only.
- E2E test API key in tests/e2e/Scopes/ProjectCustom.php gains
  insights.read/write/manager + reports.read/write so the manager
  endpoint is reachable from the test harness.
- E2E InsightsBase.createInsight() helper now POSTs /manager/insights.
- New testCreateRequiresManagerScope verifies a key with
  insights.read/write but no insights.manager is rejected with 401.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:20:49 +12:00
Damodar Lohani c9ad685e11 fix(indexes): use empty lengths for mixed-type composite to match existing pattern
greptile flagged missing lengths but the codebase has two conventions:
- all-string composite: [LENGTH_KEY, LENGTH_KEY] (_key_unique, _key_provider_providerUid)
- mixed/non-string composite: [] (e.g. ('enabled', 'type'), ('region', 'accessedAt'),
  ('targetInternalId', 'topicInternalId'), ('period', 'time'), ('metric', 'period', 'time'))

(teamInternalId, confirm) is string+boolean; closest match is
('enabled', 'type') which uses lengths => [] and orders => [].
Aligning to that established pattern instead of inventing
[LENGTH_KEY, 0].
2026-05-06 04:48:53 +00:00
Damodar Lohani 83d56a2f36 fix(indexes): set explicit lengths + orders on new indexes (greptile P1)
All four new indexes left lengths/orders as empty arrays; greptile
flagged the inconsistency vs every existing string-attribute index in
the file (e.g. _key_team uses [LENGTH_KEY], _key_unique uses
[LENGTH_KEY, LENGTH_KEY]).

- memberships._key_team_confirm: [LENGTH_KEY, 0] for (string, boolean)
  + [ORDER_ASC, ORDER_ASC]
- projects._key_teamInternalId: [LENGTH_KEY] + [ORDER_ASC]
- platforms._key_project_id: [LENGTH_KEY] + [ORDER_ASC]
- webhooks._key_project_id: [LENGTH_KEY] + [ORDER_ASC]
2026-05-06 04:44:58 +00:00
Jake BarnbyandClaude Opus 4.7 a1f64c6f71 refactor(insights): split CTA action into service + method
- InsightCTA model now exposes `service` (SDK namespace) and `method`
  (function name) instead of a single `action` string. Drops the
  string-splitting burden on every consumer and lets the console reach
  the right SDK method directly.

- Validator requires both `service` and `method` non-empty; same
  16-entry max still enforced.

- Endpoint normalization (Create + Update) splits the new shape into
  the persisted CTA descriptor.

- Constants split: INSIGHT_CTA_SERVICE_* (databases / tablesDB /
  documentsDB / vectorsDB) and INSIGHT_CTA_METHOD_* (createIndex).

- Insight model + InsightCTA model docs updated with the new field
  semantics and per-engine examples.

- E2E factory `sampleCTA($id, $engine)` emits the correct service and
  engine-appropriate params keys (tableId/columns for tablesDB;
  collectionId/attributes everywhere else). Engine matrix asserts
  `service` and `method` independently.

- Added e2e + unit coverage for the new failure modes (missing
  service, missing method, empty service, empty method).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:35:33 +12:00
Damodar Lohani 94c968e941 feat(indexes): add 4 missing indexes (CLO-2333)
- memberships: _key_team_confirm on (teamInternalId, confirm) for team-membership confirm-state queries
- projects: _key_teamInternalId on teamInternalId for team-scoped project lookups
- platforms: _key_project_id on projectId for user-facing-id lookups
- webhooks: _key_project_id on projectId for user-facing-id lookups

Re-applies the indexes from the stale PR #9629 (1.7.x base, conflicting)
onto a fresh 1.9.x branch. None of these are in 1.9.x today; existing
similar indexes target projectInternalId / teamId rather than the
user-facing projectId / teamInternalId queries this addresses.
2026-05-06 04:35:29 +00:00