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 aTenantDomainmapped to a default role carrying thesiss.psppermission. 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-svcandworkflow-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.