diff --git a/server/routes.guards.json b/server/routes.guards.json index fb4d35e..65b850a 100644 --- a/server/routes.guards.json +++ b/server/routes.guards.json @@ -1731,10 +1731,20 @@ }, { "method": "GET", - "path": "/api/v1/public/teams/:slug/members", - "handlers": 2, + "path": "/api/v1/public/teams/:slug/activity", + "handlers": 3, "gates": [ - "siteMode" + "siteMode", + "optionalAuth" + ] + }, + { + "method": "GET", + "path": "/api/v1/public/teams/:slug/members", + "handlers": 3, + "gates": [ + "siteMode", + "optionalAuth" ] }, { diff --git a/server/routes.manifest.json b/server/routes.manifest.json index be09566..db16620 100644 --- a/server/routes.manifest.json +++ b/server/routes.manifest.json @@ -705,6 +705,10 @@ "method": "GET", "path": "/api/v1/public/teams/:slug" }, + { + "method": "GET", + "path": "/api/v1/public/teams/:slug/activity" + }, { "method": "GET", "path": "/api/v1/public/teams/:slug/members" diff --git a/server/swagger/swagger-output.json b/server/swagger/swagger-output.json index 60a8b1b..e0477dc 100644 --- a/server/swagger/swagger-output.json +++ b/server/swagger/swagger-output.json @@ -10527,13 +10527,85 @@ } } }, + "/api/v1/public/teams/{slug}/activity": { + "get": { + "tags": [ + "Public · Teams" + ], + "summary": "A Team’s activity feed, filtered to what the caller may see", + "description": "Items are `public` or `members`. Anyone who can see the Team gets the public ones; members and forum-granted users also get the members-only ones, and the response says which via `scope` so a client can render \"some items are hidden\" rather than presenting a filtered feed as the whole one. Sending a session is optional.", + "parameters": [ + { + "name": "slug", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "The Team slug." + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Page size, max 100 (default 50)." + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Rows to skip (default 0)." + } + ], + "responses": { + "200": { + "description": "One page of the feed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicTeamActivity" + } + } + } + }, + "404": { + "description": "No such Team, or it is hidden from this caller", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "503": { + "description": "Service Unavailable" + } + }, + "security": [ + {}, + { + "cookieAuth": [] + }, + { + "bearerAuth": [] + } + ] + } + }, "/api/v1/public/teams/{slug}/members": { "get": { "tags": [ "Public · Teams" ], "summary": "Get a Team roster", - "description": "In-game display names only. A member key is a game-internal identifier and a user id names a site account; neither is published. `linked` answers whether a character has an account behind it without saying which.", + "description": "In-game display names only. A member key is a game-internal identifier and a user id names a site account; neither is published, whatever the module’s projection answers. `linked` answers whether a character has an account behind it without saying which. WHICH rows appear is the module’s audience projection; sending a session is optional and may widen it.", "parameters": [ { "name": "slug", @@ -10569,7 +10641,16 @@ "503": { "description": "Service Unavailable" } - } + }, + "security": [ + {}, + { + "cookieAuth": [] + }, + { + "bearerAuth": [] + } + ] } }, "/api/v1/public/version": { @@ -17081,6 +17162,23 @@ "example": 12 } } + }, + "enabled": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "boolean" + }, + "description": { + "type": "string", + "example": "Whether this deployment has Teams at all — a provider is registered, or Teams exist from one that since went away. The `teams` nav feature flag resolves from this; false means bare core, where a Teams link would lead to a permanently empty page." + }, + "example": { + "type": "boolean", + "example": true + } + } } } } @@ -17225,6 +17323,238 @@ "example": true } } + }, + "projected": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "boolean" + }, + "description": { + "type": "string", + "example": "Whether the module applied its own audience projection to this roster. False means the module declined or does not project, and the roster was served at core’s public shape — never the full one." + }, + "example": { + "type": "boolean", + "example": true + } + } + } + } + } + } + }, + "PublicTeamActivityItem": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "object" + }, + "description": { + "type": "string", + "example": "`summary` is already-rendered text supplied by whoever pushed the item; core never composes one. `kind` and `payload` are opaque to core — only the module’s `team.overview` slot renders anything richer than the text." + }, + "properties": { + "type": "object", + "properties": { + "id": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "integer" + }, + "example": { + "type": "number", + "example": 4821 + } + } + }, + "source": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "description": { + "type": "string", + "example": "`core` or a module id." + }, + "example": { + "type": "string", + "example": "uo" + } + } + }, + "kind": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "example": { + "type": "string", + "example": "uo.champion.completed" + } + } + }, + "summary": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "example": { + "type": "string", + "example": "Completed Champion Neira" + } + } + }, + "visibility": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "enum": { + "type": "array", + "example": [ + "public", + "members" + ], + "items": { + "type": "string" + } + } + } + }, + "occurredAt": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "format": { + "type": "string", + "example": "date-time" + } + } + }, + "payload": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "object" + }, + "nullable": { + "type": "boolean", + "example": true + }, + "additionalProperties": { + "type": "boolean", + "example": true + } + } + } + } + } + } + }, + "PublicTeamActivity": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "object" + }, + "properties": { + "type": "object", + "properties": { + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "array" + }, + "items": { + "$ref": "#/components/schemas/PublicTeamActivityItem" + } + } + }, + "total": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "integer" + }, + "description": { + "type": "string", + "example": "Matching rows for THIS caller’s visibility, so paging is honest." + }, + "example": { + "type": "number", + "example": 137 + } + } + }, + "limit": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "integer" + }, + "example": { + "type": "number", + "example": 50 + } + } + }, + "offset": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "integer" + }, + "example": { + "type": "number", + "example": 0 + } + } + }, + "scope": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "string" + }, + "enum": { + "type": "array", + "example": [ + "public", + "members" + ], + "items": { + "type": "string" + } + }, + "description": { + "type": "string", + "example": "Which visibilities this caller received. `public` means members-only items were withheld — render that fact rather than presenting a filtered feed as the whole one." + } + } } } }