todo.sr.ht/api/graph/schema.graphqls

409 lines
10 KiB
GraphQL

scalar Cursor
scalar Time
# Used to provide a human-friendly description of an access scope
directive @scopehelp(details: String!) on ENUM_VALUE
enum AccessScope {
PROFILE @scopehelp(details: "profile information")
TRACKERS @scopehelp(details: "trackers")
TICKETS @scopehelp(details: "tickets")
ACLS @scopehelp(details: "access control lists")
EVENTS @scopehelp(details: "events")
SUBSCRIPTIONS @scopehelp(details: "tracker & ticket subscriptions")
}
enum AccessKind {
RO @scopehelp(details: "read")
RW @scopehelp(details: "read and write")
}
# Decorates fields for which access requires a particular OAuth 2.0 scope with
# read or write access.
directive @access(scope: AccessScope!, kind: AccessKind!) on FIELD_DEFINITION
# https://semver.org
type Version {
major: Int!
minor: Int!
patch: Int!
# If this API version is scheduled for deprecation, this is the date on which
# it will stop working; or null if this API version is not scheduled for
# deprecation.
deprecationDate: Time
}
interface Entity {
canonicalName: String!
}
type User implements Entity {
id: Int!
created: Time!
updated: Time!
canonicalName: String!
username: String!
email: String!
url: String
location: String
bio: String
trackers(cursor: Cursor): TrackerCursor! @access(scope: TRACKERS, kind: RO)
}
type EmailAddress implements Entity {
canonicalName: String!
# "jdoe@example.org" of "Jane Doe <jdoe@example.org>"
mailbox: String!
# "Jane Doe" of "Jane Doe <jdoe@example.org>"
name: String
}
type ExternalUser implements Entity {
canonicalName: String!
# <service>:<service specific details...>
# e.g. github:ddevault
externalId: String!
# The canonical external URL for this user, e.g. https://github.com/ddevault
externalUrl: String
}
type Tracker {
id: Int!
created: Time!
updated: Time!
owner: Entity!
name: String!
description: String
tickets(cursor: Cursor): TicketCursor! @access(scope: TICKETS, kind: RO)
labels(cursor: Cursor): LabelCursor!
# Only available to the tracker owner:
acls(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)
# If the authenticated user is subscribed to this tracker, this is that
# subscription.
subscription: TrackerSubscription @access(scope: SUBSCRIPTIONS, kind: RO)
# The access control list entry (or the default ACL) which describes the
# authenticated user's permissions with respect to this tracker.
acl: ACL
}
enum TicketStatus {
REPORTED
CONFIRMED
IN_PROGRESS
PENDING
RESOLVED
}
enum TicketResolution {
UNRESOLVED
FIXED
IMPLEMENTED
WONT_FIX
BY_DESIGN
INVALID
DUPLICATE
NOT_OUR_BUG
}
enum Authenticity {
# The server vouches for this information as entered verbatim by the
# attributed entity.
AUTHENTIC
# The server does not vouch for this information as entered by the attributed
# entity, no authentication was provided.
UNAUTHENTICATED
# The server has evidence that the information has likely been manipulated by
# a third-party.
TAMPERED
}
type Ticket {
id: Int!
created: Time!
updated: Time!
submitter: Entity! @access(scope: PROFILE, kind: RO)
tracker: Tracker! @access(scope: TRACKERS, kind: RO)
# Canonical ticket reference string; may be used in comments to identify the
# ticket from anywhere.
ref: String!
subject: String!
body: String
status: TicketStatus!
resolution: TicketResolution!
authenticity: Authenticity!
labels: [Label]!
assignees: [Entity]! @access(scope: PROFILE, kind: RO)
events(cursor: Cursor): EventCursor! @access(scope: EVENTS, kind: RO)
# If the authenticated user is subscribed to this ticket, this is that
# subscription.
subscription: TicketSubscription @access(scope: SUBSCRIPTIONS, kind: RO)
# The access control list entry (or the default ACL) which describes the
# authenticated user's permissions with respect to this ticket.
acl: ACL
}
interface ACL {
# Permission to view tickets
browse: Boolean!
# Permission to submit tickets
submit: Boolean!
# Permission to comment on tickets
comment: Boolean!
# Permission to edit tickets
edit: Boolean!
# Permission to resolve, re-open, transfer, or label tickets
triage: Boolean!
}
# These ACLs are configured for specific entities, and may be used to expand or
# constrain the rights of a participant.
type TrackerACL implements ACL {
id: Int!
created: Time!
tracker: Tracker! @access(scope: TRACKERS, kind: RO)
entity: Entity! @access(scope: PROFILE, kind: RO)
browse: Boolean!
submit: Boolean!
comment: Boolean!
edit: Boolean!
triage: Boolean!
}
# These ACL policies are applied non-specifically, e.g. the default ACL for all
# authenticated users.
type DefaultACL implements ACL {
browse: Boolean!
submit: Boolean!
comment: Boolean!
edit: Boolean!
triage: Boolean!
}
type Label {
id: Int!
created: Time!
name: String!
tracker: Tracker! @access(scope: TRACKERS, kind: RO)
# In CSS hexadecimal format
backgroundColor: String!
foregroundColor: String!
tickets(cursor: Cursor): TicketCursor! @access(scope: TICKETS, kind: RO)
}
enum EventType {
CREATED
COMMENT
STATUS_CHANGE
LABEL_ADDED
LABEL_REMOVED
ASSIGNED_USER
UNASSIGNED_USER
USER_MENTIONED
TICKET_MENTIONED
}
# Represents an event which affects a ticket. Multiple changes can occur in a
# single event, and are enumerated in the "changes" field.
type Event {
id: Int!
created: Time!
changes: [EventDetail]!
ticket: Ticket! @access(scope: TICKETS, kind: RO)
}
interface EventDetail {
eventType: EventType!
ticket: Ticket!
}
type Created implements EventDetail {
eventType: EventType!
ticket: Ticket!
author: Entity!
}
type Assignment implements EventDetail {
eventType: EventType!
ticket: Ticket!
assigner: Entity!
assignee: Entity!
}
type Comment implements EventDetail {
eventType: EventType!
ticket: Ticket!
author: Entity!
text: String!
authenticity: Authenticity!
# If this comment has been edited, this field points to the new revision.
superceededBy: Comment
}
type LabelUpdate implements EventDetail {
eventType: EventType!
ticket: Ticket!
labeler: Entity!
label: Label!
}
type StatusChange implements EventDetail {
eventType: EventType!
ticket: Ticket!
editor: Entity!
oldStatus: TicketStatus!
newStatus: TicketStatus!
oldResolution: TicketResolution!
newResolution: TicketResolution!
}
type UserMention implements EventDetail {
eventType: EventType!
ticket: Ticket!
author: Entity!
mentioned: Entity!
}
type TicketMention implements EventDetail {
eventType: EventType!
ticket: Ticket!
author: Entity!
mentioned: Ticket!
}
interface Subscription {
id: Int!
created: Time!
}
# A tracker subscription will notify a participant of all activity for a
# tracker, including all new tickets and their events.
type TrackerSubscription implements Subscription {
id: Int!
created: Time!
tracker: Tracker! @access(scope: TRACKERS, kind: RO)
}
# A ticket subscription will notify a participant when activity occurs on a
# ticket.
type TicketSubscription implements Subscription {
id: Int!
created: Time!
ticket: Ticket! @access(scope: TICKETS, kind: RO)
}
# A cursor for enumerating trackers
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type TrackerCursor {
results: [Tracker]!
cursor: Cursor
}
# A cursor for enumerating tickets
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type TicketCursor {
results: [Ticket]!
cursor: Cursor
}
# A cursor for enumerating labels
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type LabelCursor {
results: [Label]!
cursor: Cursor
}
# A cursor for enumerating access control list entries
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type ACLCursor {
results: [TrackerACL]!
cursor: Cursor
}
# A cursor for enumerating events
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type EventCursor {
results: [Event]!
cursor: Cursor
}
# A cursor for enumerating subscriptions
#
# If there are additional results available, the cursor object may be passed
# back into the same endpoint to retrieve another page. If the cursor is null,
# there are no remaining results to return.
type SubscriptionCursor {
results: [Subscription]!
cursor: Cursor
}
type Query {
# Returns API version information.
version: Version!
# Returns the authenticated user.
me: User! @access(scope: PROFILE, kind: RO)
# Returns a specific user.
user(username: String!): User @access(scope: PROFILE, kind: RO)
# Returns trackers that the authenticated user has access to.
#
# NOTE: in this version of the API, only trackers owned by the authenticated
# user are returned, but in the future the default behavior will be to return
# all trackers that the user either (1) has been given explicit access to via
# ACLs or (2) has implicit access to either by ownership or group membership.
trackers(cursor: Cursor): TrackerCursor @access(scope: TRACKERS, kind: RO)
tracker(id: Int!): Tracker @access(scope: TRACKERS, kind: RO)
# Returns a specific tracker, owned by the authenticated user.
trackerByName(name: String!): Tracker @access(scope: TRACKERS, kind: RO)
# Returns a specific tracker, owned by the given canonical name (e.g.
# "~sircmpwn").
trackerByOwner(owner: String!, tracker: String!): Tracker @access(scope: TRACKERS, kind: RO)
# List of events which the authenticated user is subscribed to or implicated
# in, ordered by the event date (recent events first).
events(cursor: Cursor): EventCursor @access(scope: EVENTS, kind: RO)
# List of subscriptions of the authenticated user.
subscriptions(cursor: Cursor): SubscriptionCursor @access(scope: SUBSCRIPTIONS, kind: RO)
}