openapi: 3.0.3 info: title: PyraFiles API version: 1.0.0 description: | API specification for the PyraFiles application. PyraFiles allows users to register, authenticate, manage namespaces, generate JWT tokens for agents, and manage media files within namespaces. servers: - url: http://127.0.0.1:{port} description: Local development server variables: port: default: '6544' - url: https://files.example.com description: Production server paths: /: get: summary: Home Page description: Displays the home page with public namespaces and user namespaces. responses: '200': description: Successful response content: text/html: schema: type: string /auth/login: get: summary: Display Login Page description: Renders the login page where users can enter their email. responses: '200': description: Login page rendered content: text/html: schema: type: string post: summary: Process Login description: Sends a verification code to the user's email. requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: email: type: string format: email required: - email responses: '302': description: Redirects to the verification page headers: Location: description: URL of the verification page schema: type: string '400': description: Bad Request (e.g., email missing) /auth/verify: get: summary: Display Verification Page description: Renders the verification page where users can enter their code. responses: '200': description: Verification page rendered content: text/html: schema: type: string post: summary: Verify User description: Verifies the user's code and logs them in. requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: code: type: string required: - code responses: '302': description: Redirects to the home page upon successful verification headers: Location: description: URL of the home page schema: type: string '400': description: Bad Request (e.g., invalid code) /auth/logout: post: summary: Logout User description: Logs out the current user. security: - sessionAuth: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: csrf_token: type: string responses: '302': description: Redirects to the home page headers: Location: description: URL of the home page schema: type: string '403': description: Unauthorized (user not logged in) /auth/profile: get: summary: Display User Profile description: Shows the user's profile, including owned namespaces. security: - sessionAuth: [] responses: '200': description: Profile page rendered content: text/html: schema: type: string '403': description: Unauthorized (user not logged in) post: summary: Update User Profile description: Updates the user's profile settings. security: - sessionAuth: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: enable_gravatar: type: string enum: ['on'] new_username: type: string encoding: enable_gravatar: contentType: text/plain new_username: contentType: text/plain responses: '302': description: Redirects to the profile page headers: Location: description: URL of the profile page schema: type: string '400': description: Bad Request (e.g., username already in use) '403': description: Unauthorized (user not logged in) /namespace/create: get: summary: Display Namespace Creation Page description: Renders the form to create a new namespace. security: - sessionAuth: [] responses: '200': description: Namespace creation page rendered content: text/html: schema: type: string '403': description: Unauthorized (user not logged in) post: summary: Create Namespace description: Processes the namespace creation form. security: - sessionAuth: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: name: type: string is_public: type: string enum: ['on'] encoding: name: contentType: text/plain is_public: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '400': description: Bad Request (e.g., namespace name already exists) '403': description: Unauthorized (user not logged in) /namespace/{namespace_short_id}/manage: get: summary: Manage Namespace (Owners Only) description: Displays the namespace management page. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace responses: '200': description: Namespace management page rendered content: text/html: schema: type: string '403': description: Forbidden (not owner or not logged in) '404': description: Namespace not found /namespace/{namespace_short_id}/update: post: summary: Update Namespace (Owners Only) description: Updates namespace properties. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: is_public: type: string enum: ['on'] description: 'Checkbox value. Present if checked.' encoding: is_public: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '403': description: Forbidden (not owner or not logged in) '404': description: Namespace not found /namespace/{namespace_short_id}/invite: post: summary: Invite User to Namespace (Owners Only) description: Invites a user to the namespace with a specified role. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: email: type: string format: email role: type: string enum: ['owner', 'editor', 'reader'] required: - email - role encoding: email: contentType: text/plain role: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '400': description: Bad Request (e.g., invalid role) '403': description: Forbidden (not owner or not logged in) '404': description: Namespace not found /namespace/{namespace_short_id}/remove_user: post: summary: Remove User from Namespace (Owners Only) description: Removes a user from the namespace. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: user_id: type: string required: - user_id encoding: user_id: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '400': description: Bad Request (e.g., cannot remove self) '403': description: Forbidden (not owner or not logged in) '404': description: Namespace or user not found /namespace/{namespace_short_id}/change_member_role: post: summary: Change Member Role in Namespace (Owners Only) description: Changes a member's role in the namespace. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: user_id: type: string role: type: string enum: ['owner', 'editor', 'reader'] required: - user_id - role encoding: user_id: contentType: text/plain role: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '400': description: Bad Request (e.g., cannot change own role) '403': description: Forbidden (not owner or not logged in) '404': description: Namespace or user not found /namespace/{namespace_short_id}/generate_agent_jwt: post: summary: Generate Agent JWT (Owners Only) description: Generates a JWT token for an agent. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: agent_name: type: string agent_role: type: string enum: ['owner', 'editor', 'reader'] required: - agent_name - agent_role encoding: agent_name: contentType: text/plain agent_role: contentType: text/plain responses: '200': description: Agent JWT generated and displayed content: text/html: schema: type: string '400': description: Bad Request (e.g., agent name missing) '403': description: Forbidden (not owner or not logged in) '404': description: Namespace not found /namespace/{namespace_short_id}/revoke_agent: post: summary: Revoke Agent (Owners Only) description: Revokes an agent's access by invalidating their JWT. **Requires 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string description: The short ID of the namespace requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: agent_id: type: string required: - agent_id encoding: agent_id: contentType: text/plain responses: '302': description: Redirects to the namespace management page headers: Location: description: URL of the namespace management page schema: type: string '400': description: Bad Request (e.g., agent ID missing) '403': description: Forbidden (not owner or not logged in) '404': description: Namespace or agent not found /namespace/{namespace_short_id}/media/upload: get: summary: Display Media Upload Page (Editors and Owners) description: Renders the media upload form. **Requires 'editor' or 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string responses: '200': description: Media upload page rendered content: text/html: schema: type: string '403': description: Forbidden (insufficient permissions) post: summary: Upload Media (Editors and Owners) description: Uploads a media file to the namespace. **Requires 'editor' or 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string requestBody: required: true content: multipart/form-data: schema: type: object properties: media_file: type: string format: binary title: type: string is_public: type: string enum: ['on'] required: - media_file responses: '302': description: Redirects to the media details page headers: Location: description: URL of the media details page schema: type: string '400': description: Bad Request (e.g., file missing) '403': description: Forbidden (insufficient permissions) '404': description: Namespace not found /namespace/{namespace_short_id}/media/list: get: summary: List Media in Namespace description: Lists all media files in the namespace. security: - sessionAuth: [] - agentAuth: [] - {} # Allow public access if namespace is public parameters: - in: path name: namespace_short_id required: true schema: type: string responses: '200': description: Media list page rendered content: text/html: schema: type: string '403': description: Forbidden (insufficient permissions) '404': description: Namespace not found /namespace/{namespace_short_id}/media/{media_short_id}/details: get: summary: View Media Details description: Displays the details of a media file. security: - sessionAuth: [] - agentAuth: [] - {} # Allow public access if media is public parameters: - in: path name: namespace_short_id required: true schema: type: string - in: path name: media_short_id required: true schema: type: string responses: '200': description: Media details page rendered content: text/html: schema: type: string '403': description: Forbidden (insufficient permissions) '404': description: Media or namespace not found /namespace/{namespace_short_id}/media/{media_short_id}/edit: get: summary: Display Media Edit Page (Editors and Owners) description: Renders the media edit form. **Requires 'editor' or 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string - in: path name: media_short_id required: true schema: type: string responses: '200': description: Media edit page rendered content: text/html: schema: type: string '403': description: Forbidden (insufficient permissions) '404': description: Media or namespace not found post: summary: Edit Media (Editors and Owners) description: Updates the media file or metadata. **Requires 'editor' or 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string - in: path name: media_short_id required: true schema: type: string requestBody: required: true content: multipart/form-data: schema: type: object properties: title: type: string media_file: type: string format: binary is_public: type: string enum: ['on'] responses: '302': description: Redirects to the media details page headers: Location: description: URL of the media details page schema: type: string '400': description: Bad Request (e.g., invalid data) '403': description: Forbidden (insufficient permissions) '404': description: Media or namespace not found /namespace/{namespace_short_id}/media/{media_short_id}/delete: post: summary: Delete Media (Editors and Owners) description: Deletes the specified media file. **Requires 'editor' or 'owner' role.** security: - sessionAuth: [] - agentAuth: [] parameters: - in: path name: namespace_short_id required: true schema: type: string - in: path name: media_short_id required: true schema: type: string requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: csrf_token: type: string responses: '302': description: Redirects to the media list page headers: Location: description: URL of the media list page schema: type: string '403': description: Forbidden (insufficient permissions) '404': description: Media or namespace not found /namespace/{namespace_short_id}/media/{media_short_id}: get: summary: View or Download Media description: Serves the media file for viewing or downloading. security: - sessionAuth: [] - agentAuth: [] - {} # Allow public access if media is public parameters: - in: path name: namespace_short_id required: true schema: type: string - in: path name: media_short_id required: true schema: type: string - in: query name: download schema: type: boolean description: Set to true to download the file responses: '200': description: Media file served content: '*/*': schema: type: string format: binary '403': description: Forbidden (insufficient permissions) '404': description: Media or namespace not found components: securitySchemes: sessionAuth: type: apiKey in: cookie name: session description: Session cookie for authenticated users agentAuth: type: http scheme: bearer bearerFormat: JWT description: JWT authentication for agents