docs(rfc): add 0011 api architecture #24
No reviewers
Labels
No labels
needs/docs
needs/research
needs/upstream
type/bug
type/external
type/feature
type/refactor
urgency
high
urgency
immediate
urgency
low
urgency
medium
No milestone
No project
No assignees
10 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
ScottyLabs/terrier!24
Loading…
Reference in a new issue
No description provided.
Delete branch "rfc/0011-api-architecture"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Kennel Deployments
Last updated for commit
b589bc9.some thoughts on open question 3. administration
(even less coherent) thoughts on open question 7. submission schema
open question 11. offline connectivity, real-time, and retry behavior is one of the subprojects. if anyone has opinions we would love to hear it :)
I'm kind of leaning towards having every hackathon be its own Terrier instance
It would simplify things a lot and maybe we could store a config file that people can reuse? This needs more discussion.
@kritdass wrote in #24 (comment):
we don't want this, it makes deployment significantly more complicated for orgs and also removes the ability to have an archive of past hackathons (which is also a feature we need)
So we should provide a UI for hackathon creation?
@kritdass wrote in #24 (comment):
yes
Some thoughts:
@ipae wrote in #24 (comment):
Unlikely to be that often of an issue except for a few day-of things. Last-updated check with confirmation should be sufficient.
Definitely. Honestly, I’m not sure Terrier even needs a way to display winners, but if they do it should absolutely not be anything more than a list organizers manually curate.
Definitely a +1 on bulk operations. We do a lot of those. Yeah, indication of failure should be per element as well. Inspiration could be taken from Chihuahua’s flow for bulk operations.
Also to keep in mind: it may be more efficient to pull data out of Terrier to analyze, then upload the results (e.g. acceptances), so the possibility for external workflows should be considered while going through this planning process.
Kind of a nitpicky detail:
RFC 0008 currently states that there is "one role per user per hackathon"
However, the current roles are 'hacker', 'organizer', 'judge', and 'sponsor'
It should technically be possible for a 'sponsor' to also have the 'judge' role, as detailed in the User Flow RFC where sponsors can "self-select as a judge for any of the company's prize tracks."
It could be that a 'sponsor' role implies they have judging permissions for their track, which is likely the better (and current) solution, but perhaps that should be further detailed/clarified in the RFC.
I can't really imagine any other two or more roles needing to be applied to a single user, so this hopefully also resolves one of the many questions in Open Question #3: "Can users hold multiple hackathon roles, and are additional roles such as mentor needed?"
Some thoughts on open question 9:
On open question 6:
@ -0,0 +121,4 @@| `POST /api/v1/hackathons` | Create a hackathon with its settings | Global-admin access || `GET /api/v1/hackathons/{slug}` | Read hackathon configuration visible to the caller | Public fields or management view || `PATCH /api/v1/hackathons/{slug}` | Update hackathon settings | Hackathon management || `DELETE /api/v1/hackathons/{slug}` | Remove or deactivate a hackathon | Hackathon management; semantics unresolved |Should this deactive the hackathon first then delete after a certain amount of time in case it needs to be reversed?
i recommend that all mutations, deletions included, populate a write-only log so that accidental mutations can be reverted by admins/organizers. this obviously necessitates that deletions should always use some sort of
deletedflag and never truly delete databecause in that case, we'd only have database backups to do any sort of disaster recovery -- these must happen through manual tickets to computing services and they take a while to act on those requests. they're also only in-session on weekdays from 8am to 5pm and usually don't get to your request same-day
@ -0,0 +37,4 @@### ArchitectureThe API lives in `crates/terrier-server`. Axum handles HTTP requests, SeaORM accesses PostgreSQL, and `utoipa-axum` registers routes and generates the OpenAPI specification. The Svelte frontend and Tauri mobile client consume the same API through generated TypeScript types and `openapi-fetch`.to be consistent with o-quest and the future maps mobile app, terrier should use capacitor, not tauri
@ -0,0 +265,4 @@### Offline ConnectivityTerrier should remain usable during a Wi-Fi outage and automatically synchronize locally saved work as soon as connectivity returns and the client can run. Judges must be able to view previously downloaded assignments and project details and save evaluations locally while offline. Preserve pending evaluations across normal reloads and application restarts, then send them automatically when reconnected. Show distinct states for saved on this device, awaiting sync, confirmed by the server, and failed or needs attention; local persistence is not server acceptance.the most important thing here is that you actually display a persistent, non-blocking indicator while the client is offline (a la ubereats, spotify, slack). It should explain the remaining content here, i.e. that work is being saved on this device and that new assignments and updates cannot be retrieved until connectivity returns.
it would also be useful to indicate when cached assignments and project details were last refreshed. this should ideally be implemented in the api client layer so that every mutation/access inherits it (and the indicator should similarly be in/close to the root layout).
otherwise, the recovery/graceful degradation behaviors described here don't actually do anything to qualm the user's confusion (showing "sync status" is not enough)
@ -0,0 +301,4 @@These are decisions for the RFC PR. Revise the detailed design as they are answered before acceptance; a deliberately deferred feature should have its scope and follow-up recorded.1. <a id="question-api-version-retirement"></a> **API version retirement.** How long do we support a previous major version, how do we announce deprecation and retirement, and what upgrade path do unsupported mobile clients receive? Major-version routes, pinned web and mobile clients, and the latest-stable `/api` alias are established above.terrier is deployed and distributed as a single binary, and thus there is only ever one supported version of the api (the version that an organization is hosting).
furthermore, due to the app store's limitation, we can only have one build of terrier on the app store at any given point. thus the api version is further restricted to a single one for everyone who may be hosting terrier at any given point
because of this, i recommend dropping API version altogether and include automatic app updating as o-quest does
@ -0,0 +312,4 @@1. <a id="question-results"></a> **Results.** Both immediate organizer publication and scheduled release are supported. How are scheduled releases changed or canceled? Who can see results before release? Are we publishing winners, rankings, aggregate scores, or raw evaluations? How should organizers correct or revoke publication during recovery, and should results be stored as a snapshot?1. <a id="question-communications"></a> **Communications and integrations.** Which channels and providers ship first, and how should their integrations work end to end? How do organizers connect accounts, grant permissions, and disconnect or replace an integration? What adapter interfaces, credential storage, recipient/channel mappings, and workflow triggers are needed? How do outgoing API calls and incoming webhooks or status updates interact with delivery records, and how are callbacks authenticated and deduplicated? Who configures integrations, and which setup, testing, failure inspection, and manual recovery controls do organizers need? Are scheduling, cancellation, and delivery-status reads required? Are recipients resolved when scheduled or when sent? What consent, retry, duplicate-send, and partial-failure rules apply? How do application and team notifications use this system?1. <a id="question-real-time-and-retry-behavior"></a> **Offline connectivity, real-time, and retry behavior.** Offline access to downloaded judging data, locally saved evaluations, visible sync status, and automatic synchronization on reconnect are required. How should the web and mobile implementations cache application resources and data, persist pending work, and handle reloads, storage failures, and expired authentication? What works while clients are closed or suspended? Which workflows beyond judging should work offline? How should retries avoid duplicate evaluations and handle changed assignments or judging deadlines? Which changes need WebSocket events? How are subscriptions authorized and state recovered on reconnect? Which writes need idempotency keys or other retry guarantees beyond database uniqueness?1. <a id="question-prize-distribution"></a> **Prize distribution.** The integration with Chihuahua remains open. Rust-to-Python FFI is under consideration, but no integration mechanism has been selected. Should Terrier hand published winners to Chihuahua through FFI, an API, or an export, and what data and failure-handling contract would that require? Chihuahua handles winner details and financial forms; the handoff contract remains to be defined. Keep payment and tax-form handling outside this RFC until that boundary is agreed.chihuahua is super tartanhacks/CMU-specific, recommend either distinguishing it from terrier entirely or creating an interface that is sufficiently generic. this means you should definitely not introduce python FFI for this
Regarding open question #5 ("Teams"):
I think there should be some kind of built-in team matching system that other organizations using Terrier can modify if they want (like choose between users being recommended teams based on best match, have users see all teams accepting applications, etc.).
But I think generally each user should be able to set a public profile, including their name, experience (frontend, backend, etc.), and maybe some other stuff. I know cal hacks had a thing like a dating app where they could swipe on other user profiles (not other teams) and find matches based on that.
For leadership transfers, I think we could make it so that the leader needs to first transfer leadership before being able to leave the team.
I'm still not really sure about who gets to remove people from the team. Because if the leader gets to remove them at any time, then if you join a random team they could remove you last-minute and you would be kinda cooked. So maybe the leader just can't remove people from the team after they are accepted?
Maybe teams can only be deleted when the leader is the only member in the team. Then in order to delete a team, everyone would leave it first (representing their approval to delete team) and then the leader would delete it. If one person doesn't agree for some reason, the leader could just transfer leader to that one person and then leave. Actually this ability for the team members to show their approval for team deletion by leaving first could be further reason to only allow members to leave a team when they want to and not when the leader removes them.
Team details could be only-editable by leader.
Users should be able to apply to several teams, so maybe they just join whichever team they get accepted to first (because otherwise if there's a chance that they won't join a team even after a team accepts them that could be messy for the team).
Organizers should be able to do basically anything to a team like recover it and stuff just in case there are any accidents or it needs to be done for some reason (I don't see how this could be a bad thing?) But there should be rules, for example, organizers can't get involved when there's a dispute between team members or something.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.