2026-05-01 02:04:36 +00:00
|
|
|
<?php
|
|
|
|
|
|
2026-05-11 01:59:31 +00:00
|
|
|
namespace Tests\E2E\Services\Advisor;
|
2026-05-01 02:04:36 +00:00
|
|
|
|
|
|
|
|
use Tests\E2E\Client;
|
|
|
|
|
use Utopia\Database\Helpers\ID;
|
|
|
|
|
|
2026-05-11 01:59:31 +00:00
|
|
|
trait AdvisorBase
|
2026-05-01 02:04:36 +00:00
|
|
|
{
|
|
|
|
|
protected function serverHeaders(): array
|
|
|
|
|
{
|
|
|
|
|
return [
|
|
|
|
|
'content-type' => 'application/json',
|
|
|
|
|
'x-appwrite-project' => $this->getProject()['$id'],
|
|
|
|
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 08:20:54 +00:00
|
|
|
protected function getReport(string $reportId, ?array $headers = null): array
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
|
|
|
|
return $this->client->call(Client::METHOD_GET, '/reports/' . $reportId, $headers ?? $this->serverHeaders());
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 08:20:54 +00:00
|
|
|
protected function listReports(array $params = [], ?array $headers = null): array
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
|
|
|
|
return $this->client->call(Client::METHOD_GET, '/reports', $headers ?? $this->serverHeaders(), $params);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 08:20:54 +00:00
|
|
|
protected function getInsight(string $reportId, string $insightId, ?array $headers = null): array
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
2026-05-06 06:53:54 +00:00
|
|
|
return $this->client->call(Client::METHOD_GET, '/reports/' . $reportId . '/insights/' . $insightId, $headers ?? $this->serverHeaders());
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 08:20:54 +00:00
|
|
|
protected function listInsights(string $reportId, array $params = [], ?array $headers = null): array
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
2026-05-06 06:53:54 +00:00
|
|
|
return $this->client->call(Client::METHOD_GET, '/reports/' . $reportId . '/insights', $headers ?? $this->serverHeaders(), $params);
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
public function testListReports(): void
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
{
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
$list = $this->listReports();
|
|
|
|
|
|
|
|
|
|
$this->assertSame(200, $list['headers']['status-code']);
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->assertArrayHasKey('reports', $list['body']);
|
|
|
|
|
$this->assertArrayHasKey('total', $list['body']);
|
|
|
|
|
$this->assertIsArray($list['body']['reports']);
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
public function testGetReportMissing(): void
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
2026-05-08 06:07:23 +00:00
|
|
|
$missing = $this->getReport(ID::unique());
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
|
|
|
|
|
$this->assertSame(404, $missing['headers']['status-code']);
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->assertSame('report_not_found', $missing['body']['type']);
|
2026-05-01 02:04:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
public function testListInsightsMissingReport(): void
|
2026-05-01 02:04:36 +00:00
|
|
|
{
|
2026-05-08 06:07:23 +00:00
|
|
|
$missing = $this->listInsights(ID::unique());
|
2026-05-01 02:04:36 +00:00
|
|
|
|
|
|
|
|
$this->assertSame(404, $missing['headers']['status-code']);
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->assertSame('report_not_found', $missing['body']['type']);
|
2026-05-01 02:04:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
public function testGetInsightMissingReport(): void
|
2026-05-01 02:04:36 +00:00
|
|
|
{
|
2026-05-08 06:07:23 +00:00
|
|
|
$missing = $this->getInsight(ID::unique(), ID::unique());
|
2026-05-01 02:04:36 +00:00
|
|
|
|
|
|
|
|
$this->assertSame(404, $missing['headers']['status-code']);
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->assertSame('report_not_found', $missing['body']['type']);
|
2026-05-01 02:04:36 +00:00
|
|
|
}
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
|
2026-05-12 13:15:43 +00:00
|
|
|
public function testReportsCreateAndUpdateNotExposed(): void
|
refactor(insights): metadata-only CTAs, platform DB, reports parent
Address review feedback on PR #12194:
- Pivot CTAs to pure descriptors (id/label/action/params). Drop the
server-side execution layer: Action interface, registry, the
databases.indexes.create CTA action, the params validator, the
/v1/insights/:id/ctas/:id/executions endpoint, the InsightCTAExecution
model, the INSIGHT_CTA_* errors, and the corresponding events. The
console invokes the existing public API directly with the descriptor's
action + params.
- Restore Databases\Indexes\Action.php to its pre-CTA shape and inline
the index-create body back into Create.php (the createIndex helper
was added solely for CTA reuse).
- Move insights collection from project DB to platform DB and add a
parent reports collection alongside it. Insights carry projectId /
projectInternalId for tenant scoping and an optional reportId for
grouping. List endpoints filter by projectInternalId; Get/Update/
Delete also enforce project ownership before touching the document.
- New Reports module with full CRUD (Create/Get/XList/Update/Delete),
Report response model, Reports query validator, REPORT_NOT_FOUND /
REPORT_ALREADY_EXISTS errors, reports.read / reports.write scopes,
and reports.* event tree. Delete cascades to child insights.
- Update.php now mutates the loaded document via setAttribute (instead
of passing a partial new Document), reuses CTAsValidator (instead of
the looser ArrayList<JSON> + isset check), and rejects duplicate CTA
ids.
- Create.php enforces unique CTA ids during normalization.
- CTAsValidator gained a configurable maxCount (default 16) so the
Create path matches the Update path and the DB column size, and
oversized payloads return a clean 400.
- Validator\Queries\Insights adds status and reportId to
ALLOWED_ATTRIBUTES so dismissal / report workflows are filterable.
- Realtime channel parser guards $parts[1] for both insights and
reports event names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:46:07 +00:00
|
|
|
{
|
2026-05-08 06:07:23 +00:00
|
|
|
$create = $this->client->call(Client::METHOD_POST, '/reports', $this->serverHeaders(), [
|
|
|
|
|
'reportId' => ID::unique(),
|
|
|
|
|
'type' => 'audit',
|
|
|
|
|
'title' => 'Read-only check',
|
|
|
|
|
'targetType' => 'sites',
|
|
|
|
|
'target' => 'home',
|
|
|
|
|
]);
|
|
|
|
|
$this->assertSame(404, $create['headers']['status-code']);
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
$update = $this->client->call(Client::METHOD_PATCH, '/reports/' . ID::unique(), $this->serverHeaders(), [
|
|
|
|
|
'title' => 'Read-only check',
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
]);
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->assertSame(404, $update['headers']['status-code']);
|
2026-05-12 13:15:43 +00:00
|
|
|
}
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
|
2026-05-12 13:15:43 +00:00
|
|
|
public function testDeleteReportMissing(): void
|
|
|
|
|
{
|
2026-05-08 06:07:23 +00:00
|
|
|
$delete = $this->client->call(Client::METHOD_DELETE, '/reports/' . ID::unique(), $this->serverHeaders());
|
|
|
|
|
$this->assertSame(404, $delete['headers']['status-code']);
|
2026-05-12 13:15:43 +00:00
|
|
|
$this->assertSame('report_not_found', $delete['body']['type']);
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-12 13:15:43 +00:00
|
|
|
public function testInsightsCreateUpdateDeleteNotExposed(): void
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
{
|
2026-05-12 13:15:43 +00:00
|
|
|
$create = $this->client->call(
|
2026-05-08 06:07:23 +00:00
|
|
|
Client::METHOD_POST,
|
2026-05-12 13:15:43 +00:00
|
|
|
'/reports/' . ID::unique() . '/insights',
|
2026-05-08 06:07:23 +00:00
|
|
|
$this->serverHeaders(),
|
|
|
|
|
[]
|
|
|
|
|
);
|
2026-05-12 13:15:43 +00:00
|
|
|
$this->assertSame(404, $create['headers']['status-code']);
|
2026-05-06 06:53:54 +00:00
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
$update = $this->client->call(
|
|
|
|
|
Client::METHOD_PATCH,
|
|
|
|
|
'/reports/' . ID::unique() . '/insights/' . ID::unique(),
|
|
|
|
|
$this->serverHeaders(),
|
|
|
|
|
['status' => 'dismissed']
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(404, $update['headers']['status-code']);
|
2026-05-06 06:53:54 +00:00
|
|
|
|
2026-05-08 06:07:23 +00:00
|
|
|
$delete = $this->client->call(
|
|
|
|
|
Client::METHOD_DELETE,
|
|
|
|
|
'/reports/' . ID::unique() . '/insights/' . ID::unique(),
|
|
|
|
|
$this->serverHeaders()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(404, $delete['headers']['status-code']);
|
test(insights): full e2e + per-engine CTA action mapping
- Restructure InsightsBase trait with explicit helper methods
(createInsight/getInsight/listInsights/updateInsight/deleteInsight,
createReport/getReport/listReports/updateReport/deleteReport, plus
sampleInsight/sampleCTA factories) — same shape ProxyBase uses.
- Add coverage for: report CRUD + duplicate-id rejection, invalid type
rejection, list filtering by all allowed attributes, cursor
pagination + missing-cursor, update preserving untouched fields,
CTA validation edge cases (duplicate ids, empty fields, count > 16),
dismissal round-trip + status filter, report cascade delete,
unauthorized access (no server key), empty-result list.
- Engine-specific insight types (tablesDBIndex, documentsDBIndex,
vectorsDBIndex, plus the legacy databaseIndex) so the CTA's `action`
can map to the matching public API: databases.createIndex,
tablesDB.createIndex, documentsDB.createIndex,
vectorsDB.createIndex. dataProvider drives the engine matrix and
asserts the right action lands in the persisted CTA. Constants for
each action name live in app/init/constants.php.
- InsightCTA model docs spell out which action belongs to which engine
and that the params keys differ between APIs (tableId/columns for
tablesDB vs collectionId/attributes for the legacy / DocumentsDB /
VectorsDB APIs).
- Insight model `type` description now lists every engine variant.
- CTAsTest gains coverage for object-shaped params, empty-action and
empty-label rejection, and the default 16-entry cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:25:49 +00:00
|
|
|
}
|
2026-05-01 02:04:36 +00:00
|
|
|
}
|