Skip to content

Develop#43

Merged
0xmanhnv merged 32 commits into
mainfrom
develop
Apr 14, 2026
Merged

Develop#43
0xmanhnv merged 32 commits into
mainfrom
develop

Conversation

@0xmanhnv
Copy link
Copy Markdown
Collaborator

No description provided.

0xmanhnv added 30 commits April 14, 2026 03:56
…/services/public

1. State History: 5 specialized endpoints now delegate to main List handler
   with pre-set event_type filters. New ?event_type= param on GET /state-history.
   All old endpoints still work (backward compat).

2. Facets: replace N+1 queries (1 + up to 15) with single query using
   jsonb_object_keys() set-returning function. Groups by key/val in SQL,
   Go code picks top 20 values per key.

3. GET /services/public: deprecated, delegates to List with is_public=true.
   Use GET /services?is_public=true instead.
- POST /quick-scan → POST /scans/quick (old kept for backward compat)
- GET /scan-management/stats → GET /scans/overview-stats (old kept)
- GET /tool-stats → GET /tenant-tools/stats (old kept)
- Mark POST /agent/ingest as deprecated alias for /agent/ingest/ctis
- Suppress controller 'no items' debug log noise
…ement, tool-stats)

Endpoints consolidated into parent groups:
- POST /quick-scan → POST /scans/quick (old removed)
- GET /scan-management/stats → GET /scans/overview-stats (old removed)
- GET /tool-stats → GET /tenant-tools/stats (old removed)

/agent/ingest kept as primary CTIS ingest endpoint (SDK/agent compat).
HIGH fixes:
- Bulk actions: bulk-enable/bulk-disable/bulk-sync → bulk/enable, bulk/disable, bulk/sync
- Path params: snake_case → camelCase (cve_id→cveId, comment_id→commentId, etc.)
- {ownerID} → {ownerId} (consistent camelCase)
- {memberId} → {userId} in tenant routes (consistent with groups/pentest)
- Handler PathValue/URLParam updated to match new param names

MEDIUM fixes:
- /admin/admins → /admin/users (redundant word)
- /config/finding-sources → /finding-sources (orphaned namespace)
- /ai-triage/config → /findings/ai-triage/config (consolidate namespace)
Backend:
- Add PATCH /remediation/campaigns/{id} for full campaign update
- Add UpdateRemediationCampaignInput + UpdateCampaign service method
- Add SetName/SetDescription/SetPriority/SetDueDate domain methods
- Add ThreatIntelRefreshController — daily EPSS + KEV refresh (24h interval)
- Register controller in workers.go
…fication

When a finding has fix_applied status, trigger a targeted scan on the
affected asset to verify the fix. Uses QuickScan with verification context.

- Add VerificationScanTrigger interface (decoupled from scan package)
- Add verificationScanTriggerAdapter wrapping scan.Service.QuickScan
- Add RequestVerificationScan service method + handler
- Wire adapter in services.go
…erty

If asset type is 'domain' but properties.root_domain differs from the
asset name (e.g., name='a.ipas.com.vn', root_domain='ipas.com.vn'),
auto-change type to 'subdomain'. Prevents mistyped subdomains from
collectors.
PromoteKnownProperties now detects subdomains using two methods:
1. root_domain property from collector (if provided)
2. Domain level computation from name structure — handles .com.vn,
   .co.uk, .com.au and 30+ known second-level TLDs

Migration 000133 fixes existing prod data: any asset typed 'domain'
that has a parent domain in the same tenant is reclassified as 'subdomain'.

Example: 'enterpriseenrollment.ipa.com.vn' (type=domain) → type=subdomain
because 'ipa.com.vn' exists as a root domain.
When ?type=subdomain or ?type=domain is in URL:
- Skip tree flattening (no Root/Sub hierarchy confusion)
- Hide Type column (Root/Sub badges not relevant)
- Show plain flat list of filtered assets

Fixes: subdomains showing as 'Root' when no parent domains in dataset.
…t properties

Extract from properties.domain.dns_records into flat top-level keys:
- record_type (first record's type: A, CNAME, AAAA, etc.)
- resolved_ip (first A/AAAA value)
- cname_target (first CNAME value)
- ttl, dns_record_types, resolved_ips, dns_record_count
- Normalize root_domain (strip trailing dot)
PromoteKnownProperties now extracts from domain.dns_records:
- record_type (first record's A/CNAME/AAAA)
- resolved_ip / resolved_ips (A/AAAA values)
- cname_target (CNAME value)
- ttl, dns_record_types, dns_record_count
- Normalize root_domain (strip trailing dot)

Future ingests will have flat fields automatically.
Combined with migration 000134 for existing data.
…g page wire

Control Testing:
- Add Create Control Test dialog (POST /control-tests)
- Add MITRE Coverage table from simulations data
- Replace Untested card with Coverage % stat

Ticketing (Jira):
- Wire page to real /integrations?category=ticketing API
- Add Connect dialog (Jira/Linear/Asana providers)
- Sync button calls POST /integrations/{id}/sync
- Stats from real integration metadata
- Generic camelToSnakeCase() converter in PromoteKnownProperties — normalizes ALL
  JSONB property keys on ingest (replaces hardcoded 8-key map)
- Migration 000135: batch convert existing camelCase JSONB keys to snake_case
- Jira sync service + webhook handler for bidirectional finding↔ticket sync
- Control test scheduler controller for stale detection coverage
- Fix unchecked error in component_repository KEV query
- Add GetByWorkItemURI + UpdateWorkItemURIs stubs to 5 test mock structs
- 2 new unit tests for camelToSnake normalization + duplicate key handling
- Add PUT /api/v1/business-units/{id} — Update handler + service + route
- Threat intel controller now calls SyncAll() (fetch + persist to DB)
  instead of just logging fetched data
- Risk reduction recorded on campaign completion (finding count delta)
- TODO: wire WorkflowEventDispatcher for auto verification scan trigger
ListDistinctTags now accepts types []string to scope tags to current
asset type. On hosts page, tag filter only shows host tags (not
network/domain tags). Handler reads ?type= query params.
GET /assets/stats?count_by=is_virtual,ssl,os returns metadata_counts
in response. Backend adds UNION ALL per field with GROUP BY on JSONB
property value. Only alphanumeric+underscore field names allowed
(SQL injection safe). Single CTE scan — no extra queries.
Migration 000136: relationship_suggestions table with status workflow
Domain: Suggestion entity with Approve/Dismiss lifecycle
Repository: Postgres CRUD with ON CONFLICT DO NOTHING for dedup
Service: GenerateSuggestions (subdomain→root, domain→IP by DNS)
Handler: List, Approve, Dismiss, ApproveAll, Generate, CountPending
Routes: /api/v1/relationships/suggestions/* endpoints

Phase 1 rules:
- subdomain → parent domain (member_of, confidence 1.0)
- domain/subdomain with resolved_ip → ip_address asset (resolves_to, 1.0)
- ListPending now JOINs assets table to include source/target name + type
- API response includes source_asset_name, source_asset_type, etc.
- Frontend shows asset names and type badges in suggestion table
- ListPending: search param (ILIKE on JOINed asset names)
- ApproveBatch: POST /suggestions/approve-batch with ids array
- Default sort: confidence DESC, created_at DESC
- Fix CRITICAL IDOR: add tenant_id to asset Update WHERE clause
- Fix scalability: replace hardcoded LIMIT 100 with pagination loop
  (fetchAllAssets) so tenants with >100 assets get complete suggestions
- Fix relationship type: use contains (parent→child) instead of cname_of
  for domain→subdomain hierarchy, matching project design philosophy
- Add PATCH /{id}/type endpoint for inline relationship type editing
- Add per-tenant rate limit (30s cooldown) on /generate endpoint
- Add max batch size validation (1000 IDs) on ApproveBatch
- Return error when all batch items fail instead of silent success
- Update YAML constraints: contains allows domain→subdomain,
  resolves_to allows subdomain as source, cname_of strictly DNS CNAME
- Regenerate Go + TypeScript types from YAML
Comment thread internal/infra/postgres/relationship_suggestion_repository.go Fixed
Comment thread internal/infra/postgres/relationship_suggestion_repository.go Fixed
@0xmanhnv 0xmanhnv merged commit bdb730b into main Apr 14, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants