diff --git a/gms/README.md b/gms/README.md
new file mode 100644
index 00000000..c509f0d3
--- /dev/null
+++ b/gms/README.md
@@ -0,0 +1,93 @@
+# Groups Management Service (gms)
+
+The ***gms*** service provides RESTful web service interface for group management operations. It handles creation, modification, deletion, and querying of user groups, as well as managing group memberships and permissions.
+
+This service works with a user service that provides user identity information. TBD
+
+## deployment
+The `gms` war file can be renamed at deployment time in order to support an alternate service name, including
+introducing additional path elements.
+See cadc-tomcat (war-rename.conf).
+
+## configuration
+The following runtime configuration must be made available via the `/config` directory.
+
+### catalina.properties
+This file contains java system properties to configure the tomcat server and some of the java libraries
+used in the service.
+
+See cadc-tomcat for
+system properties related to the deployment environment.
+
+See cadc-util for common system properties.
+
+### cadc-registry.properties
+
+See cadc-registry.
+
+### gms.properties
+TBD. At minimum, the following properties are required:
+- Corresponding user service base URL and the name of the user identity attribute.
+
+## API Overview
+
+The GMS service provides the following operations:
+
+### Group Management
+- **List all groups** - GET /groups
+- **Create group** - PUT /groups
+- **Get group** - GET /groups/{groupName}
+- **Delete group** - DELETE /groups/{groupName}
+- **Modify group** - POST /groups/{groupName}
+- **Add/Remove user members** - POST/DELETE /groups/{groupName}/userMembers
+- **Add/Remove group members** - POST/DELETE /groups/{groupName}/groupMembers/{groupName2} (Is it required to distinguish between user and group members?)
+
+### Group Searching
+- **Search by role** - GET /search?id={userID}&idType={idType}&role={role}
+- **Search specific membership** - GET /search?group={groupIVOID} (repeatable; see OpenAPI)
+
+### Authentication Methods
+The service supports multiple authentication methods:
+- **Client certificates** (CC) over HTTPS - `/groups/*` endpoints
+- **Anonymous** (AN) access for listing operations
+
+## Group Structure
+
+Groups have the following key components:
+- **Owner** - Can modify administrator/member lists and delete the group
+- **Administrators** - Can modify administrator and member lists
+- **Members** - Are granted access to resources the group is associated with
+
+Both users and other groups can be members or administrators of a group.
+
+## building it
+```
+gradle clean build
+docker build -t gms -f Dockerfile .
+```
+
+## running it
+```
+docker run --rm --user tomcat:tomcat --volume=/path/to/external/config:/config:ro --name gms gms:latest
+```
+
+## testing it
+
+### Unit tests
+```
+gradle clean test
+```
+
+### Integration tests
+```
+gradle clean intTest
+```
+
+For local testing against a running instance:
+```
+~/bin/int-test-localhost.sh
+```
+
+## API Documentation
+
+For detailed API specifications including request/response formats, authentication requirements, and error codes, see the OpenAPI specification or the service capabilities endpoint at `/capabilities`.
diff --git a/gms/model.puml b/gms/model.puml
new file mode 100644
index 00000000..2d8fa212
--- /dev/null
+++ b/gms/model.puml
@@ -0,0 +1,65 @@
+@startuml GMS Domain Model
+
+class Group {
+ - uri: URI
+ - description: String
+ - gid: Integer
+ - lastModified: Date
+ - owner: User
+ - userMembers: Set
+ - userAdmins: Set
+ - groupMembers: Set
+ - groupAdmins: Set
+}
+
+class User {
+ - identity: Identity
+ - firstName: String
+ - lastName: String
+ - email: String
+}
+
+class Identity {
+ - type: String
+ - value: String
+}
+
+enum IdentityType {
+ X500
+ OPENID
+ NUMERIC
+}
+
+enum Role {
+ OWNER
+ ADMIN
+ MEMBER
+}
+
+' Relationships
+Group "1" *-- "1" User : owner
+Group "1" o-- "0..*" User : userMembers
+Group "1" o-- "0..*" User : userAdmins
+Group "1" o-- "0..*" Group : groupMembers
+Group "1" o-- "0..*" Group : groupAdmins
+
+User "1" *-- "1" Identity : key identity
+
+Identity ..> IdentityType : <>
+Group ..> Role : <>
+
+note right of Group
+ A group can contain both
+ users and other groups as
+ members or administrators
+end note
+
+note left of User
+ Users are identified by
+ a configurable identity
+ (primary key) that the
+ corresponding user service
+ provides
+end note
+
+@enduml
diff --git a/gms/src/main/webapp/openapi.yaml b/gms/src/main/webapp/openapi.yaml
new file mode 100644
index 00000000..bb28388c
--- /dev/null
+++ b/gms/src/main/webapp/openapi.yaml
@@ -0,0 +1,59 @@
+## GMS OpenAPI root: path items under ./openapi/; shared parameters/schemas in ./openapi/components.yaml; standard HTTP error fragments in ./openapi/vosi/vosi-std-responses.yaml (avoid `$ref` from fragments back into this file — that can deadlock libopenapi/vacuum).
+openapi: 3.1.0
+info:
+ title: CANFAR Group Management System (GMS) API
+ description: |
+ This API provides RESTful access to group management operations in the CANFAR Group Management System.
+
+ Groups have an owner, a list of administrators, and a list of members. The list of members and
+ administrators can be composed of groups and users.
+
+ **Roles:**
+ - **owner** - Can modify administrators list and members list. Can delete the group.
+ - **admin** - Can modify the administrators and members list.
+ - **member** - Are granted access to the resources the group is associated with.
+
+ **Authentication Methods:**
+ - **CC** - Client certificates over HTTPS
+ - **JWT** - JWT Bearer token over HTTPS
+ - **AN** - Anonymous over HTTP
+
+ **User Identity:**
+ Users are identified by their unique userID in the Identity Provider (CANFAR HTTP username).
+ version: 1.0.0
+ contact:
+ url: https://www.canfar.net
+tags:
+ - name: Group Management
+ description: Operations for managing groups
+ - name: GMS
+ description: Operations for searching groups by user role (IVOA GMS 1.0)
+ - name: Group Membership
+ description: GMS membership and identity-related queries
+ - name: VOSI Capabilities
+ description: VOSI capability and probe operations
+ - name: Service availability
+ description: Service availability
+ - name: POSIX Groups
+ description: POSIX group id (gid) and group name mapping
+servers:
+ - url: /gms
+
+paths:
+ /capabilities:
+ $ref: ./openapi/vosi/vosi-capabilities.yaml
+ /availability:
+ $ref: ./openapi/cadcvosi/availability.yaml
+ /groups:
+ $ref: ./openapi/service/group.yaml#/GroupsCollection
+ /groups/{groupName}:
+ $ref: ./openapi/service/group.yaml#/GroupById
+ /groups/{groupName}/userMembers/{userID}:
+ $ref: ./openapi/service/group.yaml#/GroupUserMembers
+ /groups/{groupName}/groupMembers/{groupName2}:
+ $ref: ./openapi/service/group.yaml#/GroupGroupMembers
+ /search:
+ $ref: ./openapi/gms/gms-search.yaml
+ /gidmap:
+ $ref: ./openapi/pm/posix-groupmap.yaml
+
diff --git a/gms/src/main/webapp/openapi/cadcvosi/availability.yaml b/gms/src/main/webapp/openapi/cadcvosi/availability.yaml
new file mode 100644
index 00000000..e4887f37
--- /dev/null
+++ b/gms/src/main/webapp/openapi/cadcvosi/availability.yaml
@@ -0,0 +1,31 @@
+get:
+ operationId: read-availability
+ tags:
+ - Service availability
+ summary: Returns the availability status of the service
+ description: Get the set of descriptions for this service.
+ responses:
+ '200':
+ description: Service is available
+ content:
+ application/xml:
+ schema:
+ type: object
+ xml:
+ name: availability
+ properties:
+ available:
+ type: boolean
+ example: true
+ xml:
+ name: availability
+ prefix: vosi
+ namespace: http://www.ivoa.net/xml/VOSIAvailability/v1.0
+ note:
+ type: string
+ example: service is accepting requests
+ example:
+ available: true
+ note: service is accepting requests
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
diff --git a/gms/src/main/webapp/openapi/components.yaml b/gms/src/main/webapp/openapi/components.yaml
new file mode 100644
index 00000000..47be1074
--- /dev/null
+++ b/gms/src/main/webapp/openapi/components.yaml
@@ -0,0 +1,88 @@
+# Shared components for the GMS OpenAPI description (referenced from path fragments and the root document).
+components:
+ parameters:
+ groupName:
+ name: groupName
+ in: path
+ required: true
+ description: |
+ The group name (simple identifier), e.g. teamA, myGroup
+ schema:
+ type: string
+ example: teamA
+ userID:
+ name: userID
+ in: path
+ required: true
+ description: The unique user identifier (CANFAR HTTP username)
+ schema:
+ type: string
+ example: user1
+ idType:
+ name: idType
+ in: query
+ description: The type of userID (http, x509, cadc)
+ required: true
+ schema:
+ type: string
+ enum:
+ - http
+ - x509
+ - cadc
+ example: http
+
+ schemas:
+ Group:
+ type: object
+ description: Representation of a group
+ User:
+ type: string
+ description: User identifier (CANFAR HTTP username)
+ example: "exampleuser"
+
+ examples:
+ example-group:
+ summary: Example group document (JSON/XML body shape)
+ value:
+ uri: "ivo://cadc.nrc.ca/gms#teamA"
+ owner: "owner1"
+ description: "Research team access group"
+ lastModified: "2015-07-24T17:38:18.000"
+ userMembers:
+ - "member1"
+ - "member2"
+ - "member3"
+ userAdmins:
+ - "admin1"
+ - "admin2"
+ groupMembers:
+ - uri: "ivo://cadc.nrc.ca/gms#shared-data"
+ - uri: "ivo://cadc.nrc.ca/gms#pipeline-users"
+ groupAdmins:
+ - uri: "ivo://cadc.nrc.ca/gms#platform-admins"
+
+ GroupXmlDetailed:
+ summary: Detailed group example (XML)
+ value: |
+
+ ivo://cadc.nrc.ca/gms#teamA
+ owner1
+ Research team access group
+ 2015-07-24T17:38:18.000
+
+ member1
+ member2
+ member3
+
+
+ admin1
+ admin2
+
+
+ ivo://cadc.nrc.ca/gms#shared-data
+ ivo://cadc.nrc.ca/gms#pipeline-users
+
+
+ ivo://cadc.nrc.ca/gms#platform-admins
+
+
diff --git a/gms/src/main/webapp/openapi/gms/gms-search.yaml b/gms/src/main/webapp/openapi/gms/gms-search.yaml
new file mode 100644
index 00000000..3f9c99cf
--- /dev/null
+++ b/gms/src/main/webapp/openapi/gms/gms-search.yaml
@@ -0,0 +1,83 @@
+get:
+ tags:
+ - GMS
+ summary: Query group membership
+ description: |
+ Returns group memberships for the authenticated identity.
+
+ If one or more `group` parameters are supplied, the response SHALL
+ contain only those groups for which membership is confirmed.
+
+ If no `group` parameter is supplied, the response SHALL contain all
+ groups of which the identity is a member.
+
+ The response SHALL be plain text containing zero or more lines,
+ each line containing a simple group name.
+ operationId: getMembership
+
+ parameters:
+ - name: group
+ in: query
+ description: Membership of one or more groups.
+ required: false
+ schema:
+ type: array
+ items:
+ type: string
+ example:
+ - "group1"
+ - "group2"
+ - "group3"
+
+ responses:
+ '200':
+ description: Successful membership response
+ content:
+ text/plain:
+ schema:
+ type: string
+ description: |
+ Plain text response listing simple group names, one per line.
+ examples:
+ filtered:
+ summary: Filtered by requested groups
+ value: |
+ groupA
+ groupC
+ allGroups:
+ summary: All memberships (no group parameter supplied)
+ value: |
+ groupA
+ groupB
+ groupC
+ none:
+ summary: No memberships
+ value: ""
+
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+
+components:
+
+ parameters:
+
+ group:
+ name: group
+ in: query
+ description: |
+ Name of a group.
+
+ This parameter MAY be repeated to test membership in multiple groups.
+
+ If omitted, all group memberships SHALL be returned.
+ required: false
+ example:
+ - ivo://example.org/gms?engineering
+ schema:
+ type: array
+ items:
+ type: string
+ example: ivo://example.org/gms?engineering
+ style: form
\ No newline at end of file
diff --git a/gms/src/main/webapp/openapi/pm/posix-groupmap.yaml b/gms/src/main/webapp/openapi/pm/posix-groupmap.yaml
new file mode 100644
index 00000000..c5106d50
--- /dev/null
+++ b/gms/src/main/webapp/openapi/pm/posix-groupmap.yaml
@@ -0,0 +1,125 @@
+get:
+ operationId: get-groupmap
+ tags:
+ - POSIX Groups
+ summary: get local posix info for groups
+ parameters:
+ - name: group
+ in: query
+ description: request only specified group records
+ required: false
+ schema:
+ type: array
+ items:
+ type: string
+ example:
+ - "ivo://foo.net/gms?group1"
+ - "ivo://foo.net/gms?group2"
+ - "ivo://bar.net/gms?group1"
+ - name: gid
+ in: query
+ description: request group record(s) by posix gid
+ schema:
+ type: array
+ items:
+ type: integer
+ example:
+ - 10001
+ - 10002
+ - 20001
+ - 20002
+ responses:
+ '200':
+ $ref: '#/components/responses/PosixGroups'
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-found
+post:
+ operationId: create-groupmap-entry
+ tags:
+ - POSIX Groups
+ summary: create a local posix info for a group
+ parameters:
+ - name: group
+ in: query
+ description: |
+ create and return a posix group entry for the specified group;
+ the value is an IVOA Group URI as defined by the GMS standard
+ required: false
+ schema:
+ type: string
+ example: "ivo://foo.net/gms?group1"
+ responses:
+ '201':
+ $ref: '#/components/responses/PosixGroups'
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-found
+ '405':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-implemented
+
+components:
+ responses:
+ PosixGroups:
+ description: list of groups with posix details
+ content:
+ text/plain:
+ description: posix groups in /etc/group format
+ schema:
+ type: string
+ example: |
+ foo_group1:x:20001:
+ foo_group2:x:20002
+ bar_group1:x:20003
+ application/x-posix-group+json:
+ description: POSIX group details as JSON array
+ schema:
+ type: array
+ example:
+ - uri: "ivo://foo.net/gms?group1"
+ posix:
+ name: foo_group1
+ gid: 20001
+ - uri: "ivo://foo.net/gms?group2"
+ posix:
+ name: foo_group2
+ gid: 20002
+ - uri: "ivo://bar.net/gms?group1"
+ posix:
+ name: bar_group1
+ gid: 20003
+ items:
+ type: object
+ example:
+ uri: "ivo://foo.net/gms?group1"
+ posix:
+ name: foo_group1
+ gid: 20001
+ required:
+ - uri
+ - posix
+ properties:
+ uri:
+ type: string
+ example: "ivo://foo.net/gms?group1"
+ posix:
+ type: object
+ example:
+ name: foo_group1
+ gid: 20001
+ required:
+ - name
+ - gid
+ properties:
+ name:
+ type: string
+ example: foo_group1
+ gid:
+ type: integer
+ example: 20001
\ No newline at end of file
diff --git a/gms/src/main/webapp/openapi/service/group.yaml b/gms/src/main/webapp/openapi/service/group.yaml
new file mode 100644
index 00000000..b3aedf1e
--- /dev/null
+++ b/gms/src/main/webapp/openapi/service/group.yaml
@@ -0,0 +1,260 @@
+# Path items for /groups and nested routes. Fragment keys are referenced from root `openapi.yaml` `paths` (Path Item objects only — no root-level `components` here).
+GroupsCollection:
+ get:
+ summary: List all groups
+ description: Lists the names of all the groups in the service
+ operationId: listGroups
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: Successful response with list of group names
+ content:
+ text/plain:
+ schema:
+ type: string
+ description: Newline-separated list of group names
+ example: |
+ group1
+ group2
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+ put:
+ summary: Create group
+ description: Create a new group according to the group XML or JSON document in the HTTP PUT
+ operationId: createGroup
+ tags:
+ - Group Management
+ requestBody:
+ description: Group data in XML or JSON format
+ required: true
+ content:
+ application/xml:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ application/json:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ responses:
+ '200':
+ description: Group created successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '404':
+ description: A member is not recognized
+ '409':
+ description: A group with the same name already exists
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+GroupById:
+ parameters:
+ - $ref: ../components.yaml#/components/parameters/groupName
+ get:
+ summary: Get group
+ description: Get the group with the specified groupName. Only users associated with the group (owner, admin, member)
+ are allowed to retrieve the group details.
+ operationId: getGroup
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: Successful response with group details
+ content:
+ application/xml:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ application/json:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: The group could not be found
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+ post:
+ summary: Modify group
+ description: Modify the group with the specified groupName according to the group XML or JSON document in the HTTP POST
+ Only the owner or administrators of the group are allowed to modify the group.
+ operationId: modifyGroup
+ tags:
+ - Group Management
+ requestBody:
+ description: Updated group data in XML or JSON format
+ required: true
+ content:
+ application/xml:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ application/json:
+ schema:
+ $ref: ../components.yaml#/components/schemas/Group
+ examples:
+ example-group:
+ $ref: ../components.yaml#/components/examples/example-group
+ responses:
+ '200':
+ description: Group modified successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: The group could not be found or a member is not recognized
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+ delete:
+ summary: Delete group
+ description: Delete the group with the specified groupName. Only the owner of the group is allowed to delete the group.
+ operationId: deleteGroup
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: Group deleted successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: The group to delete could not be found
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+GroupUserMembers:
+ parameters:
+ - $ref: ../components.yaml#/components/parameters/groupName
+ - $ref: ../components.yaml#/components/parameters/userID
+ - $ref: ../components.yaml#/components/parameters/idType
+
+ put:
+ summary: Add user member
+ description: Add a user as a member of the specified group. Only owners or administrators of the group are
+ allowed to add members.
+ operationId: addUserMember
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: User added as member successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: The group to add to could not be found or the member is not recognized
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+ delete:
+ summary: Remove user member
+ description: Remove a user as a member of the specified group. Only owners or administrators of the group are
+ allowed to remove members.
+ operationId: removeUserMember
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: User removed successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: The group could not be found or the member is not recognized
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+GroupGroupMembers:
+ parameters:
+ - $ref: ../components.yaml#/components/parameters/groupName
+ - name: groupName2
+ in: path
+ required: true
+ description: |
+ The member group name to add or remove (e.g. `teamA`, `ABCD`). Only the group owner or administrators can
+ add or remove group members.
+ schema:
+ type: string
+
+ put:
+ summary: Add group member
+ description: Add a group as a member of another group. Only internal groups can be added as members.
+ operationId: addGroupMember
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: Group member added successfully
+ '400':
+ $ref: ../vosi/vosi-std-responses.yaml#/bad-request
+ '401':
+ $ref: ../vosi/vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ../vosi/vosi-std-responses.yaml#/permission-denied
+ '404':
+ description: One or both groups could not be found
+ '500':
+ $ref: ../vosi/vosi-std-responses.yaml#/internal-server-error
+ '503':
+ $ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
+
+ delete:
+ summary: Remove group member
+ description: Remove a group as a member of another group. Only the group owner or administrators can remove
+ group members.
+ operationId: removeGroupMember
+ tags:
+ - Group Management
+ responses:
+ '200':
+ description: Group member removed successfully
diff --git a/gms/src/main/webapp/openapi/vosi/vosi-capabilities.yaml b/gms/src/main/webapp/openapi/vosi/vosi-capabilities.yaml
new file mode 100644
index 00000000..a35bf5dd
--- /dev/null
+++ b/gms/src/main/webapp/openapi/vosi/vosi-capabilities.yaml
@@ -0,0 +1,40 @@
+# Path item for /capabilities (VOSI). Must be a Path Item object only (no root-level `components` here).
+head:
+ operationId: probe-capabilities
+ tags:
+ - VOSI Capabilities
+ summary: VOSI Capabilities with SSO-next prototype
+ description: |
+ Get standard headers for the service. The standard headers should include
+ AAI related headers (www-authenticate challenges or x-vo-authenticated
+ indicator) if applicable, server name and version info, and other
+ applicable header information. SSO-next: clients use this operation to probe
+ for available authentication methods.
+ responses:
+ '200':
+ $ref: ./vosi-std-responses.yaml#/authenticated
+ '401':
+ $ref: ./vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ./vosi-std-responses.yaml#/permission-denied
+
+get:
+ operationId: read-capabilities
+ tags:
+ - VOSI Capabilities
+ summary: VOSI Capabilities with SSO-next prototype
+ description: Get the set of VOResource capability descriptions for this service.
+ responses:
+ '200':
+ description: VOSI capabilities document
+ content:
+ text/xml:
+ schema:
+ type: string
+ example: |
+
+
+ '401':
+ $ref: ./vosi-std-responses.yaml#/not-authenticated
+ '403':
+ $ref: ./vosi-std-responses.yaml#/permission-denied
diff --git a/gms/src/main/webapp/openapi/vosi/vosi-std-responses.yaml b/gms/src/main/webapp/openapi/vosi/vosi-std-responses.yaml
new file mode 100644
index 00000000..32f12e64
--- /dev/null
+++ b/gms/src/main/webapp/openapi/vosi/vosi-std-responses.yaml
@@ -0,0 +1,66 @@
+# standard
+authenticated:
+ description: a response header indicating that authentication was successful
+ headers:
+ x-vo-authenticated:
+ schema:
+ type: string
+
+not-authenticated:
+ description: |
+ Authentication is required and the current attempt failed, or credentials were not provided.
+ headers:
+ www-authenticate:
+ schema:
+ type: string
+
+permission-denied:
+ description: |
+ Caller is not authorized to perform the operation (forbidden / permission denied).
+ content:
+ text/plain:
+ schema:
+ type: string
+
+bad-request:
+ description: |
+ Invalid request or input; the URL or request body may be malformed.
+ content:
+ text/plain:
+ schema:
+ type: string
+
+not-found:
+ description: resource not found
+ content:
+ text/plain:
+ schema:
+ type: string
+
+not-implemented:
+ description: this response indicates that the service does not support this operation
+ content:
+ text/plain:
+ schema:
+ type: string
+
+too-large:
+ description: the request content exceeds a server-side limitation on size
+ content:
+ text/plain:
+ schema:
+ type: string
+
+internal-server-error:
+ description: the server encountered an unrecoverable error
+ content:
+ text/plain:
+ schema:
+ type: string
+
+service-unavailable:
+ description: the server is too busy to perform the operation
+ content:
+ text/plain:
+ schema:
+ type: string