# Platform Service API Reference

## Transport

ConnectRPC serves both protocols on port 8082:

- **Connect JSON** (HTTP/1.1) -- REST-compatible, used by app server and search clients
- **Native gRPC** (HTTP/2, binary protobuf) -- available for high-throughput callers

Compression: gzip and brotli accepted. All List RPCs support cursor-based pagination via `page_size` + `page_token`. All Update RPCs support `FieldMask` for partial updates.

### Health checks

- `GET /health` -- always 200
- `GET /health/ready` -- 200 when cache and DB are healthy, 503 if degraded

---

## Access Domain (`ows.access.v1`)

### AccessService

Core permission checking RPCs called on every request. This is the hot path.

| RPC             | Description                                                                      |
| --------------- | -------------------------------------------------------------------------------- |
| `Check`         | Check a single permission. Primary hot-path RPC.                                 |
| `CheckBatch`    | Check multiple permissions in one call. Used by UI to preload.                   |
| `GetEffective`  | Get the user's full effective permission set for a tenant. Used on login.        |
| `ResolveTenant` | Resolve tenant context from a Grass JWT identity claim. Called once per request. |

#### Check

```
CheckRequest {
  user_id       string          // Grass identity UUID
  tenant_id     string          // Target tenant
  permission    string          // e.g. "tools.snowflake.query"
  resource_type string          // optional -- for resource-scoped checks
  resource_id   string          // optional -- for resource-scoped checks
  context       map<str, str>   // optional -- for ABAC condition evaluation
}

CheckResponse {
  outcome             Outcome   // GRANTED, DENIED, or STEP_UP_REQUIRED
  reason              string    // human-readable denial reason
  missing_permission  string    // the specific permission that was missing
}
```

**Error codes:** `INVALID_ARGUMENT` (bad permission format), `NOT_FOUND` (tenant/user not found), `PERMISSION_DENIED` (access denied).

#### CheckBatch

```
CheckBatchRequest {
  user_id      string
  tenant_id    string
  permissions  repeated string
  context      map<str, str>
}

CheckBatchResponse {
  results  map<string, Outcome>  // permission -> outcome
}
```

#### GetEffective

```
GetEffectiveRequest {
  user_id    string
  tenant_id  string
}

GetEffectiveResponse {
  permissions     repeated string     // all granted permissions
  roles           repeated RoleInfo
  plan            PlanVersionInfo
  tenant          TenantInfo
  credit_balance  CreditBalanceInfo
}
```

#### ResolveTenant

```
ResolveTenantRequest {
  identity_id   string                  // Grass identity UUID
  email         string                  // Grass email
  applications  repeated GrassApplication
  profiles      repeated GrassProfile
}

ResolveTenantResponse {
  tenant_id       string
  tenant_user_id  string
  status          TenantUserStatus
  tenant_name     string
}
```

### RoleService

Role lifecycle, hierarchy, and assignment management.

| RPC                   | Description                                           |
| --------------------- | ----------------------------------------------------- |
| `CreateRole`          | Create a custom role in a tenant                      |
| `GetRole`             | Get a role by ID                                      |
| `UpdateRole`          | Update role name/description                          |
| `DeleteRole`          | Delete a custom role (system roles cannot be deleted) |
| `ListRoles`           | List roles for a tenant                               |
| `SetRolePermissions`  | Set the permission set for a role                     |
| `SetRoleInheritance`  | Set parent roles (inheritance hierarchy)              |
| `AssignRole`          | Assign a role to a user                               |
| `RevokeRole`          | Revoke a role from a user                             |
| `ListUserRoles`       | List all roles for a user in a tenant                 |
| `CreateRoleExclusion` | Create a separation-of-duty constraint                |
| `DeleteRoleExclusion` | Delete a SoD constraint                               |
| `ListRoleExclusions`  | List SoD constraints for a tenant                     |
| `ListModules`         | List permission modules                               |
| `ListPermissions`     | List permissions (optionally filtered by module)      |
| `CreateModule`        | Create a permission module                            |
| `CreatePermission`    | Create a permission within a module                   |

### PolicyService

User-level permission overrides and ABAC conditions.

| RPC                    | Description                                  |
| ---------------------- | -------------------------------------------- |
| `GrantPermission`      | Grant a direct permission override to a user |
| `DenyPermission`       | Set a deny override for a user (deny-wins)   |
| `RevokeOverride`       | Remove a direct grant or deny override       |
| `ListUserOverrides`    | List all permission overrides for a user     |
| `SetPolicyConditions`  | Attach ABAC conditions to a permission       |
| `ListPolicyConditions` | List conditions for a permission             |

### SessionService

Session lifecycle and step-up authentication.

| RPC                     | Description                           |
| ----------------------- | ------------------------------------- |
| `ListSessions`          | List active sessions for a user       |
| `RevokeSessions`        | Revoke one or all sessions for a user |
| `CreateStepUpChallenge` | Initiate a step-up auth challenge     |
| `VerifyStepUpChallenge` | Verify a completed step-up challenge  |

### PlanService

Plan versioning, tenant plan assignment, and add-on management.

| RPC                        | Description                                            |
| -------------------------- | ------------------------------------------------------ |
| `CreatePlan`               | Create a new plan version (starts as draft)            |
| `PublishPlan`              | Transition draft to active (immutable from this point) |
| `DeprecatePlan`            | Mark plan as deprecated (no new subscriptions)         |
| `SunsetPlan`               | Set a hard sunset date with auto-migration target      |
| `ListPlans`                | List all plans                                         |
| `SetTenantPlan`            | Assign a plan to a tenant                              |
| `GetTenantPlan`            | Get a tenant's current plan assignment                 |
| `MigrateTenantPlan`        | Migrate a tenant from one plan version to another      |
| `GetEffectiveEntitlements` | Get resolved entitlements (plan + add-ons + overrides) |
| `ActivateAddOn`            | Activate an add-on for a tenant                        |
| `CancelAddOn`              | Cancel an active add-on                                |

### MeteringService

Credit balance and usage tracking.

| RPC                     | Description                                |
| ----------------------- | ------------------------------------------ |
| `GetCreditBalance`      | Get current credit balance for a tenant    |
| `ListCreditEntries`     | List individual credit consumption entries |
| `GetCreditUsageSummary` | Usage breakdown by operation and user      |
| `AdjustCredits`         | Manual credit adjustment (admin)           |

---

## Platform Domain (`ows.platform.v1`)

### TenantService

Tenant lifecycle, settings, and security configuration.

| RPC                      | Description                                            |
| ------------------------ | ------------------------------------------------------ |
| `CreateTenant`           | Create a new tenant with plan and jurisdiction         |
| `GetTenant`              | Get tenant by ID                                       |
| `UpdateTenant`           | Update tenant name, jurisdiction                       |
| `ListTenants`            | List tenants (super admin)                             |
| `SuspendTenant`          | Suspend a tenant (all users lose access)               |
| `ReactivateTenant`       | Reactivate a suspended tenant                          |
| `SignupTenant`           | Self-serve tenant signup (creates tenant + admin user) |
| `GetTenantSettings`      | Get tenant configuration settings                      |
| `SetTenantSetting`       | Set a tenant configuration value                       |
| `AddIpAllowlistEntry`    | Add a CIDR to the tenant's IP allowlist                |
| `RemoveIpAllowlistEntry` | Remove a CIDR from the allowlist                       |
| `ListIpAllowlist`        | List all allowlist entries                             |
| `RequestDataExport`      | Initiate a data export (GDPR)                          |
| `RequestDataDeletion`    | Initiate data deletion (GDPR)                          |

### IdentityService

User lifecycle and super admin management.

| RPC                | Description                                      |
| ------------------ | ------------------------------------------------ |
| `ListUsers`        | List users in a tenant                           |
| `GetUser`          | Get a tenant user by ID                          |
| `SuspendUser`      | Suspend a user (revokes sessions, flushes cache) |
| `ReactivateUser`   | Reactivate a suspended user                      |
| `DeactivateUser`   | Deactivate a user (permanent)                    |
| `GrantSuperAdmin`  | Grant super admin level to a user                |
| `RevokeSuperAdmin` | Revoke super admin access                        |
| `ListSuperAdmins`  | List all super admins                            |
| `Impersonate`      | Generate an impersonation token (max 1 hour)     |

### InvitationService

User onboarding via invitations and domain-based auto-join.

| RPC                       | Description                                                              |
| ------------------------- | ------------------------------------------------------------------------ |
| `InviteUser`              | Send an invitation email to a new user                                   |
| `InviteUsersBulk`         | Invite multiple users in one call                                        |
| `AcceptInvitation`        | Accept an invitation (creates TenantUser, assigns role, records consent) |
| `ValidateInvitationToken` | Check if an invitation token is valid                                    |
| `AddDomainAllowlist`      | Add a domain for auto-join                                               |
| `VerifyDomain`            | Verify domain ownership (DNS TXT)                                        |
| `RequestAutoJoin`         | Auto-join a tenant via verified email domain                             |

### GroupService

User groups for collaboration and resource sharing.

| RPC                  | Description                                  |
| -------------------- | -------------------------------------------- |
| `CreateGroup`        | Create a user group                          |
| `AddGroupMembers`    | Add users to a group                         |
| `RemoveGroupMembers` | Remove users from a group                    |
| `ListGroups`         | List groups in a tenant                      |
| `CreateDepartment`   | Create a department (hierarchical, for ABAC) |
| `AssignDepartment`   | Assign a user to a department                |

---

## Compliance Domain (`ows.compliance.v1`)

### AuditService

Query and export audit logs.

| RPC                        | Description                                     |
| -------------------------- | ----------------------------------------------- |
| `QueryAuditLog`            | Query audit log entries with filters            |
| `QueryPermissionChangeLog` | Query permission change history                 |
| `ExportAuditLog`           | Export audit data to S3 (returns presigned URL) |

#### QueryAuditLog

```
QueryAuditLogRequest {
  tenant_id       string          // required
  user_id         string          // optional filter
  action          string          // optional filter (prefix match)
  resource        string          // optional filter (prefix match)
  outcome_filter  AuditOutcome    // optional filter
  start_time      string          // ISO 8601
  end_time        string          // ISO 8601
  limit           int32
  cursor          string          // pagination cursor
}

QueryAuditLogResponse {
  entries      repeated AuditLogEntry
  next_cursor  string
}
```

#### ExportAuditLog

```
ExportAuditLogRequest {
  tenant_id   string
  start_time  string
  end_time    string
  format      string   // "json" or "csv"
}

ExportAuditLogResponse {
  export_url  string   // S3 presigned URL
  expires_at  string
}
```

---

## Shared Enums

```
enum Outcome {
  OUTCOME_UNSPECIFIED     = 0
  OUTCOME_GRANTED         = 1
  OUTCOME_DENIED          = 2
  OUTCOME_STEP_UP_REQUIRED = 3
}

enum AuditOutcome {
  AUDIT_OUTCOME_UNSPECIFIED = 0
  AUDIT_OUTCOME_SUCCESS     = 1
  AUDIT_OUTCOME_DENIED      = 2
  AUDIT_OUTCOME_ERROR       = 3
}

enum TenantStatus {
  active | suspended | deactivated
}

enum TenantUserStatus {
  active | invited | suspended | deactivated
}

enum OverrideType {
  grant | deny
}

enum ConditionType {
  ownership | department | time_window | resource_state | ip_range | custom
}

enum SuperAdminLevel {
  full | read_only | support | product | analytics
}
```

---

## Error Handling

All RPCs use standard ConnectRPC error codes:

| Code                  | Usage                                                            |
| --------------------- | ---------------------------------------------------------------- |
| `INVALID_ARGUMENT`    | Bad input (invalid permission format, missing required fields)   |
| `NOT_FOUND`           | Entity not found (tenant, user, role, etc.)                      |
| `PERMISSION_DENIED`   | Authorization denied                                             |
| `ALREADY_EXISTS`      | Duplicate entity (role slug, invitation email)                   |
| `FAILED_PRECONDITION` | Invalid state transition (accepting already-accepted invitation) |
| `RESOURCE_EXHAUSTED`  | Rate limit or quota exceeded                                     |
| `INTERNAL`            | Unexpected server error                                          |
| `UNAVAILABLE`         | Temporary inability to serve (451 for consent required)          |
