Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fcbadd2
[backend/frontend] feat(integrations): add and display datasheet and …
Kroustille Feb 27, 2026
a613305
[frontend] feat(integrations): add datasheet and demo link fields in …
Kroustille Feb 27, 2026
2781b36
[frontend] feat(services): mutualize multiple images component across…
Kroustille Feb 27, 2026
d1388d7
[frontend] feat(services): display integration images in a carousel
Kroustille Feb 27, 2026
6ca30bb
[frontend] refactor(services): rename useSimpleServiceFormField hook
Kroustille Mar 2, 2026
3051a9c
[frontend] chore: add possibility to disable service form fields
Kroustille Mar 4, 2026
8525054
[frontend] feat: add ability to update a connector urls and images
Kroustille Mar 4, 2026
16828bb
[frontend] feat: display carousel on connector pages
Kroustille Mar 4, 2026
02ce9da
[frontend] chore: use first third party integration image as logo
Kroustille Mar 4, 2026
f9ddca7
[frontend] fix: allow deletion of datasheet or demo URLs
Kroustille Mar 4, 2026
a6dc579
[backend] chore: replace only external image by connector logo
Kroustille Mar 4, 2026
8a4f0be
[backend] test: add tests for document app and document children domain
Kroustille Mar 5, 2026
a54dfc0
[backend] chore: add migration to mark connector images as external
Kroustille Mar 5, 2026
2329175
[backend/frontend] refactor: use GraphQL enum for document source typ…
Kroustille Mar 5, 2026
e084fde
[frontend] chore: disable image edition when it is from external source
Kroustille Mar 5, 2026
3230692
[backend/frontend] chore: implement copilot review comments
Kroustille Mar 5, 2026
fada5a8
Merge branch 'development' into issue/1404
Kroustille Mar 5, 2026
6f78017
[backend/frontend] chore: implement review comments
Kroustille Mar 5, 2026
a6ef5ee
Merge branch 'development' into issue/1404
Kroustille Mar 5, 2026
b594866
[frontend] refactor(service-form): move images states into service fo…
Kroustille Mar 5, 2026
610d2fc
[frontend] fix(third-party): do not display first image in carousel o…
Kroustille Mar 6, 2026
cd1a669
[frontend] fix: display filigran logo for dashboards and scenarios
Kroustille Mar 6, 2026
368ebf4
Merge branch 'development' into issue/1404
Kroustille Mar 19, 2026
74b9f21
Merge branch 'development' into issue/1404
Kroustille Mar 20, 2026
f254ca8
Merge branch 'development' into issue/1404
Kroustille Mar 23, 2026
bb51805
Merge branch 'development' into issue/1404
Kroustille Mar 24, 2026
3c52207
[backend/frontend] feat(resources): split logo and images creation an…
Kroustille Mar 25, 2026
31e1556
Merge branch 'development' into issue/1404
Kroustille Mar 25, 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
27 changes: 27 additions & 0 deletions .github/agents/api-test-writer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
description: API test writer agent.
tools: ['insert_edit_into_file', 'replace_string_in_file', 'create_file', 'run_in_terminal', 'get_terminal_output', 'get_errors', 'show_content', 'open_file', 'list_dir', 'read_file', 'file_search', 'grep_search', 'validate_cves', 'run_subagent', 'semantic_search']
---
You are a senior backend integration test engineer for the XTM Hub monorepo. You have deep expertise in designing robust, maintainable integration tests for API and backend systems, with a strong focus on real-world data flows and best practices.

Follow these principles:
Write tests in TypeScript using Vitest.
Prefer real database calls over mocks for all *.domain.ts files. Only use mocks for external services or when testing *.app.ts files, and only when necessary.
If you need to mock, do so only for external dependencies (e.g., MinIO, Elasticsearch).
Keep tests simple, clear, and focused on real data flows.
Use the actual database (test DB) for integration tests. Clean up data between tests to ensure isolation.
Never use console.log; use logApp if logging is needed.
Prefix unused variables with _ (underscore).
Follow the repository’s structure and conventions for test files and setup/teardown.
Use the project’s constants and helpers for test data (e.g., from tests/tests.const).
Ensure tests are deterministic and do not depend on external state.
Do not write frontend or UI tests.
Ask for clarification if requirements or behaviors are ambiguous.

As a senior engineer, you are expected to:
Apply best practices for integration testing, code organization, and maintainability.
Proactively identify edge cases and ensure comprehensive coverage.
Document your tests clearly and concisely.
Mentor by example through code quality and structure.

Your goal: Write integration tests that validate the real behavior of backend modules, ensuring correctness, reliability, and maintainability at a high professional standard.
1 change: 1 addition & 0 deletions apps/portal-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"@types/config": "3.3.5",
"@types/cors": "2.8.19",
"@types/express-session": "1.18.2",
"@types/graphql-upload": "17.0.0",
"@types/node": "24.10.13",
"@types/nodemailer": "6.4.23",
"@types/passport": "1.0.17",
Expand Down
36 changes: 36 additions & 0 deletions apps/portal-api/src/__generated__/resolvers-types.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const loadConnectorChildImageIds = async (knex) => {
const parentConnectorIds = await knex('Document_Metadata')
.where({ key: 'integration_type', value: 'connector' })
.pluck('document_id');

if (!parentConnectorIds.length) return [];

const childImageIds = await knex('Document_Children')
.leftJoin('Document', 'Document_Children.child_document_id', 'Document.id')
.whereIn('Document_Children.parent_document_id', parentConnectorIds)
.andWhere('Document.type', 'image')
.pluck('Document.id');

return childImageIds;
};

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
export const up = async (knex) => {
const childImageIds = await loadConnectorChildImageIds(knex);

await knex('Document')
.whereIn('id', childImageIds)
.update({ source_type: 'external' });
};

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
export const down = async (knex) => {
const childImageIds = await loadConnectorChildImageIds(knex);

await knex('Document')
.whereIn('id', childImageIds)
.update({ source_type: 'internal' });
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const upsertConnectors = async (manifestInfo: ManifestInformation[]) => {
connector.logo,
`${connector.name}-logo.png`
);
const doc = await DocumentApp.upsertDocument<Connector>(
const doc = await DocumentApp.upsertDocumentWithExternalImage<Connector>(
OPENCTI_INTEGRATION_DOCUMENT_TYPE,
{ ...omit(connector, ['logo']) } as Connector,
uploadLogo,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest';
import {
DocumentSourceType,
IntegrationSubType,
IntegrationType,
} from '../../__generated__/resolvers-types';
Expand Down Expand Up @@ -34,7 +35,7 @@ describe('Ingest manifest helper', () => {
integration_type: IntegrationType.Connector,
manager_supported: true,
playbook_supported: false,
source_type: 'external',
source_type: DocumentSourceType.External,
service_instance_id: '0f4aad4b-bdd6-4084-8b1f-82c9c66578cc',
});
expect(result.validContracts[1]).toEqual({
Expand All @@ -54,7 +55,7 @@ describe('Ingest manifest helper', () => {
integration_type: IntegrationType.Connector,
manager_supported: false,
playbook_supported: true,
source_type: 'external',
source_type: DocumentSourceType.External,
service_instance_id: '0f4aad4b-bdd6-4084-8b1f-82c9c66578cc',
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FileUpload } from 'graphql-upload/processRequest.mjs';
import { Readable } from 'stream';
import z from 'zod';
import {
DocumentSourceType,
IntegrationSubType,
IntegrationType,
} from '../../__generated__/resolvers-types';
Expand Down Expand Up @@ -103,7 +104,7 @@ export const extractManifestInformation = (
slug: validContract.slug,
service_instance_id: INTEGRATION_SERVICE_INSTANCE_ID,
type: OPENCTI_INTEGRATION_DOCUMENT_TYPE,
source_type: 'external',
source_type: DocumentSourceType.External,
/* Document metadata properties */
container_image: validContract.container_image,
product_version: manifestData.version,
Expand Down
Loading
Loading