Skip to content

Platform integration

SISS is one CityOS module. Cross-cutting concerns — identity, tenants, module-level RBAC, and seat subscriptions — are delegated to GT Console, the shared CityOS platform service. SISS owns its domain (submission workflow, AI and BIM pipelines, signing, audit); GT Console owns the platform boundary.

Ownership split

Concern Owner
Identity (OIDC bearer tokens via GCP Identity Platform) GT Console
Canonical tenant records (CMU and PSP firms) GT Console
Module-level RBAC (coarse siss.* permissions) GT Console
Seat-based Stripe subscriptions GT Console
Usage metering (UsageEvent ingestion; OpenMeter forward) GT Console
Submission domain (submission-svc, workflow-svc, comment-svc, ai-svc, bim-svc, signing-svc, notification-svc) SISS
Object-level authorization (department RLS, per-submission policy, sign-authority, step-up) SISS
SISS audit stream (domain events → Pub/Sub → BigQuery) SISS

The split the docs use everywhere:

  • GT Console answers "Can this user touch SISS, and in what role?"
  • SISS answers "Can they touch this specific submission / sign this specific perakuan?"

Tenancy model

flowchart LR
  CMU[CMU tenant<br/>enterprise · unlimited seats<br/>admin-provisioned]
  F1[PSP firm A<br/>free tier · 10 seats]
  F2[PSP firm B<br/>paid tier · 100 seats]

  subgraph GTC[GT Console]
    CMU
    F1
    F2
  end

  GTC --> SISS[SISS]
  • CMU tenant — single tenant for the Silicon Island local authority. Admin-provisioned, unlimited seats, not Stripe-managed. Hosts CMU, ATD/ATL, SIRP, Auditor, and System.Admin users.
  • PSP firm tenants — one per firm. Default free tier (10 seats). Firm admins upgrade to paid seat tiers via GT Console's Stripe checkout when teams grow.
  • Domain-based auto-role — a firm's verified email domain (e.g. @acmearchitects.com) is registered in GT Console as a TenantDomain mapped to a default role carrying the siss.psp permission. New users from that domain are auto-granted PSP access on first login.

Tenant context is carried on every request via X-Tenant-Slug or X-Tenant-Id, per GT Console's existing convention.

Permission model

Module-level (owned by GT Console)

Coarse, namespaced, composed into GT Console roles:

Code Meaning
siss.access Baseline — can reach SISS at all
siss.psp External submitter
siss.officer Internal reviewer (CMU / ATD / ATL / SIRP)
siss.officer.sign Authorised to issue a digital signature
siss.admin Workflow config and user management within CMU tenant
siss.auditor Read-only access to the audit BigQuery dataset

The human-facing seed roles (PSP, CMU.Officer, CMU.Admin, ATD/ATL.Officer, SIRP.Officer, Auditor, System.Admin) stay as the labels used throughout this site; they compose out of the siss.* permissions above inside GT Console.

Object-level (owned by SISS)

  • Department scoping for ATD/ATL officers — AlloyDB RLS on department_id.
  • Per-submission ownership for PSPs — RLS on tenant_id (the firm) + submitter_id.
  • Sign-authority and step-up-auth gates — enforced in signing-svc and workflow-svc.

See Security & RBAC and Data for the full detail.

Subscription model

  • CMU tenant — enterprise-provisioned, unlimited seat tier, not billed through Stripe.
  • PSP firms — default free tier (10 seats). Paid upgrades available via GT Console's Stripe checkout; Stripe webhook provisions seats into the tenant.
  • Metering — GT Console ingests UsageEvents for observability and cost reporting. No SISS actions are billed at M2. OpenMeter forwarding is enabled where configured.

Baseline access is never paywalled

SISS is a regulatory submission system. Any PSP firm registered in GT Console gets baseline access on the free tier. Seat upgrades scale a firm's team size; they do not gate the ability to submit.

Request flow

Every authenticated request transits the CityOS edge, consults GT Console for module-level authorization (via the slim core-svc), then lands in the owning SISS service with object-level policy applied at the query layer.

flowchart TB
  U[PSP or officer<br/>Authorization: Bearer token<br/>X-Tenant-Slug]
  ARM[Cloud Armor · IAP · Cloud LB<br/>TLS 1.3]
  SVC[SISS service<br/>FastAPI]
  CORE[core-svc<br/>GT Console client<br/>+ decision cache · Redis<br/>+ object-level policy<br/>+ audit fan-in]
  GTC[GT Console<br/>identity · tenants<br/>module RBAC · seats]
  DB[(AlloyDB<br/>RLS applied)]
  BUS((Pub/Sub))
  BQ[(BigQuery<br/>audit)]

  U --> ARM --> SVC
  SVC -->|ingress check| CORE
  CORE -->|miss| GTC
  GTC --> CORE
  CORE --> SVC
  SVC --> DB
  CORE --> BUS --> BQ

Integration events from GT Console

Delivered via Pub/Sub subscription or HTTP webhook into core-svc:

Event Consumer behaviour
gtc.role_assignment.changed core-svc invalidates the affected user's decision cache
gtc.subscription.downgraded submission-svc blocks new user adds for the affected PSP tenant; notification-svc notifies the firm admin
gtc.tenant.suspended core-svc refuses all requests for the tenant; notification-svc alerts

These appear in the event catalog alongside the SISS domain events.

What lives in core-svc

core-svc is the slim SISS-local layer that brokers GT Console decisions. It does not own user or tenant records; GT Console is canonical.

  • GT Console client — HTTP, mTLS.
  • Policy-decision cache — Redis, short TTL, invalidated on role-change events.
  • Object-level policy resolver — department scope, sign authority, step-up gates.
  • Audit stream fan-in — SISS domain events to Pub/Sub → BigQuery.
  • GT Console event consumer — handles the three events in Integration events from GT Console above.

See core-svc in Services.

Audit correlation

GT Console maintains its own auth / role-change audit log. SISS maintains the domain-event audit stream documented in Observability. The two are complementary, not redundant. Trace IDs propagate across GT Console and SISS calls so that a single action can be traced end-to-end across both.

Open questions

Tracked on the Open issues page:

  • The exact siss.* permission catalog on this page is the docs' proposal; it needs confirmation with the GT Console team before being encoded in GT Console role definitions.
  • The integration event delivery mechanism (Pub/Sub vs. direct webhook into core-svc) is an implementation decision, not resolved here.
  • Unified audit view across GT Console and SISS is a downstream UX decision.