Suncoast Systems CMS system
kubectl apply -f manifests/Each deployed shell app should use a stable DIRECTUS_CONTENT_SITE_KEY, and that value must match the site_key on its Directus content rows. Site entries in manifests/15-directus-sites.yaml drive Directus read policies, service-token binding, and bootstrap cache-refresh defaults for those keys.
Multiple apps can share realm: external or realm: internal while using distinct app_key values and whichever site_key they read content from. Cache refresh URLs live on platform_apps (production_cache_refresh_url and preview_cache_refresh_url), so multiple deployed apps can refresh from the same content site key when needed. Add a matching app row before deploying a shell app with a new app/site key, or have the future Organization Management flow create it.
The postschema reconcile creates Directus-managed registry collections for the internal Organization Management workflow: platform_organizations, platform_apps, platform_app_operations, and platform_app_operation_steps. These store non-secret desired state, operation history, and sanitized step status only; deployment credentials stay server-side in the platform deploy service.
Directus site entries can opt into platform registry permissions with platform_management.enabled: true. The GraphQL audience alias used by the internal MFE is bound to the external site token today, so that site entry carries the platform-management grant while browser traffic still enters through Hasura and Gravitee.
The platform deploy API service, Flink preparation job, runtime manifests, and
runtime image workflows now live in platform-deploy-runtime.
This repo still owns the Directus-managed registry collections used by
Organization Management: platform_organizations, platform_apps,
platform_app_operations, and platform_app_operation_steps.
docs/directus-dynamic-selectors.md- pattern for live Directus template/slot dropdowns used by pages/blocks.docs/directus-db-change-management.md- runbook for safe Directus DB schema/data/flow changes through GitOps.docs/directus-image-action-openapi.yaml- OpenAPI spec for the in-cluster image service used by Hasura actions.docs/vm-stats-service-openapi.yaml- OpenAPI spec for the VM stats reporting endpoints.docs/cloud-billing-service-openapi.yaml- OpenAPI spec for the cloud billing aggregation API and Hasura action.docs/ui-module-contract.md- universal module contract for page components and MFEs with mandatory async configuration.docs/schemas/ui-module-definition.schema.json- JSON Schema for module definition manifests produced by module repos.docs/schemas/ui-module-instance.schema.json- JSON Schema for per-page module instances stored in CMS.docs/schemas/ui-module-event-envelope.schema.json- JSON Schema for module event/message envelopes.AGENTS.md- mandatory instructions for AI agents, including required use of the DB change-management runbook.
This service now includes a reporting framework for gathering VM health from one or more configured targets via SSH and Postgres querying.
GET /stats-> gathers all default collectors (storage, system, hardware, processes, running services, ports, sessions, log files).GET /stats?collector=storage-> only the storage collector.GET /stats?collector=hardwareorGET /stats/sections/hardware-> detailed CPU, DMI/platform, PCI, USB, block-device, and NIC inventory (hardware_raw=falsesuppresses verbose raw command output).GET /stats?collector=services-> running services by default.GET /stats?collector=services&state=all-> all services.GET /stats?collector=processes&limit=50-> top 50 processes by CPU.GET /stats?collector=service_logs&service=directus&lines=200-> today's service logs by default.GET /stats?collector=service_logs&service=directus&range=all&level=error-> error-only service logs across the available journal.GET /stats?collector=sessions&scope=db-> PostgreSQL session stats.GET /stats?collector=sessions&scope=ssh-> SSH login/session stats.GET /stats?collector=all-> same as no collector param.POST /hasura/actions/stats-> Hasura action payload wrapper aroundgetStats.GET /openapi.json-> machine-readable OpenAPI for Gravitee/Hasura integration.
The VM stats code is now fully separated into the dedicated Kubernetes service (manifests/71-vm-stats-service.yaml)
and source directory (vm-stats-service/). The GitHub profile service file (github-profile-service/src/server.ts) is restored to
profile-only behavior.
The VM stats service is a dedicated Kubernetes service with Gravitee/Hasura discovery annotations.
For local/service discovery:
- VM stats: discover via
/vm-statscontext-path on Gravitee - OpenAPI:
/openapi.jsonfromvm-stats-serviceservice route
REPORTING_ENABLED(true/false, defaultfalse)REPORTING_REQUIRE_API_KEY(true/false, defaulttrue)REPORTING_SYSTEM_ID(oracle-dbdefault; used whenREPORTING_SYSTEMS_JSONis unset)REPORTING_SYSTEMS_JSON(optional JSON array for multi-vm targeting; set throughvm-stats-service-targetsConfigMap inmanifests/71-vm-stats-service.yaml)REPORTING_SSH_HOST(required, e.g.oracle-db-vm-ip)REPORTING_SSH_USER(defaultopc)REPORTING_SSH_KEY_PATH(preferred) orREPORTING_SSH_KEY(inline key body)REPORTING_SSH_PORT(default22)REPORTING_STRICT_HOST_KEY(true/false, defaultfalse)REPORTING_COMMAND_TIMEOUT_MS(default25000)REPORTING_CONNECT_TIMEOUT_MS(default12000)REPORTING_DB_HOST(default127.0.0.1)REPORTING_DB_PORT(default5432)REPORTING_DB_NAME(defaultdirectus)REPORTING_DB_USER(defaultpostgres)REPORTING_DB_PASSWORD(optional; if missing db sessions collector returns config error)OPENAPI_SERVER_URL(optional; setsservers[].urlin/openapi.json, default/)
In this workspace, the default REPORTING_SYSTEMS_JSON is set in manifests/71-vm-stats-service.yaml to the Oracle VM target (oracle-db), using:
ssh_host:157.151.150.61db_host:157.151.150.61db_user:directus_app_k7m2v9q4x6r1t8h3
For collector metadata and thresholds, see vm-stats-service/src/server.ts env parsing section.
storage(storage utilization + threshold state)system(load, memory, swap)hardware(CPU details, cache/topology, DMI/platform, PCI, USB, block devices, network adapters)processes(top processes)services(systemd services; defaultstate=running, usestate=allfor all units)ports(listening ports and process owners)sessions(scope=db|ssh|all,limit=<n>)service_logs(service=<unit>,lines=<n>,range=today|all,level=all|warning|error,since=<timestamp>)
The cloud billing backend for the Internal Operations MFE lives in cloud-billing-service/ and is deployed by manifests/74-cloud-billing-service.yaml.
- REST summary:
GET /billing/summary - Service metadata:
GET /billing/services - Hasura action:
POST /hasura/actions/billing - OpenAPI:
GET /openapi.json - Gravitee context path:
/cloud-billing
Billing service definitions are stored in the cloud-billing-service-config ConfigMap as BILLING_SERVICES_JSON. Provider credentials are injected through optional Kubernetes Secrets:
cloud-billing-service-awscloud-billing-service-azurecloud-billing-service-gcpcloud-billing-service-ocicloud-billing-service-serverpronto
Billing runtime env vars:
BILLING_SERVICES_JSONorBILLING_CONFIG_FILE- configurable service definitions.BILLING_SHARED_BEARER_TOKEN- optional shared bearer token for direct service calls.CACHE_TTL_SECONDS,REQUEST_TIMEOUT_MS,DEFAULT_CURRENCY,CORS_ALLOW_ORIGIN,OPENAPI_SERVER_URL- runtime behavior and API metadata.
Generic providers without billing APIs use adapter: "generic" and can read costs from direct config values or env-backed Secret keys. The ServerPronto Miami colocation entry reads:
monthly-recurring-cost->SERVERPRONTO_MONTHLY_RECURRING_COSTmonth-to-date-cost->SERVERPRONTO_MONTH_TO_DATE_COSTprevious-month-cost->SERVERPRONTO_PREVIOUS_MONTH_COSTbilling-breakdown-json->SERVERPRONTO_BILLING_BREAKDOWN_JSON
For portal-only vendors, keep browser automation or AI screen parsing in a scheduled ingestion job that writes these generic billing values. Do not put portal scraping in the request path for /billing/summary.