docs(rfc): add 0011 api architecture #24

Open
kritdass wants to merge 1 commit from rfc/0011-api-architecture into main
Member
No description provided.
docs(rfc): add 0011 api architecture
All checks were successful
kennel/build build succeeded
kennel/deploy deployment healthy
nixbot/nix-eval evaluation succeeded in 0s (1 warning)
nixbot/nix-build 0 attributes built
b589bc93fa

Kennel Deployments

Service URL
docs https://terrier-docs-pr-24.scottylabs.net
terrier https://terrier-terrier-pr-24.scottylabs.net

Last updated for commit b589bc9.

<!-- kennel-deployment --> ### Kennel Deployments | Service | URL | | --- | --- | | docs | https://terrier-docs-pr-24.scottylabs.net | | terrier | https://terrier-terrier-pr-24.scottylabs.net | Last updated for commit `b589bc9`.
Member

some thoughts on open question 3. administration

  • I don't think sponsors need two permission tiers; it should be okay (for example) for any sponsor to invite a judge, or manage the prize track information.
  • it doesn't make sense for users to be able to hold multiple hackathon roles. I think we just should hardcode this in, instead of leaving it flexible.
  • I think creating hackathons should only be a global admin action. global admins should defined in environment variables I think.
  • hackathon deletion being permanent removal sounds like a bad idea. I think we should have it be deactivation in the sense that all non-admin users cannot access it.

(even less coherent) thoughts on open question 7. submission schema

  • in the database, a submission is literally a json blob iirc. it should be defined by organizers; per-hackathon (not per-instance of terrier)
  • thus.... we will probably need a new api endpoint for defining submission format? ._.
  • some things that should, by default, be in a submission format: team id (or some other identifying information), project name, tracks?
  • some things one might want to have in a submission format: long input v.s. short input, link-only input... I don't think video upload to terrier directly makes sense.

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 :)

some thoughts on open question 3. administration - I don't think sponsors need two permission tiers; it should be okay (for example) for any sponsor to invite a judge, or manage the prize track information. - it doesn't make sense for users to be able to hold multiple hackathon roles. I think we just should hardcode this in, instead of leaving it flexible. - I think creating hackathons should only be a global admin action. global admins should defined in environment variables I think. - hackathon deletion being permanent removal sounds like a bad idea. I think we should have it be deactivation in the sense that all non-admin users cannot access it. (even less coherent) thoughts on open question 7. submission schema - in the database, a submission is literally a json blob iirc. it should be defined by organizers; per-hackathon (not per-instance of terrier) - thus.... we will probably need a new api endpoint for defining submission format? ._. - some things that should, by default, be in a submission format: team id (or some other identifying information), project name, tracks? - some things one might want to have in a submission format: long input v.s. short input, link-only input... I don't think video upload to terrier directly makes sense. 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 :)
Author
Member

I'm kind of leaning towards having every hackathon be its own Terrier instance

I'm kind of leaning towards having every hackathon be its own Terrier instance
Author
Member

It would simplify things a lot and maybe we could store a config file that people can reuse? This needs more discussion.

It would simplify things a lot and maybe we could store a config file that people can reuse? This needs more discussion.
Owner

@kritdass wrote in #24 (comment):

I'm kind of leaning towards having every hackathon be its own Terrier instance

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)

@kritdass wrote in https://git.cmu.dev/ScottyLabs/terrier/pulls/24#issuecomment-19874: > I'm kind of leaning towards having every hackathon be its own Terrier instance 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)
Author
Member

So we should provide a UI for hackathon creation?

So we should provide a UI for hackathon creation?
Owner

@kritdass wrote in #24 (comment):

So we should provide a UI for hackathon creation?

yes

@kritdass wrote in https://git.cmu.dev/ScottyLabs/terrier/pulls/24#issuecomment-19889: > So we should provide a UI for hackathon creation? yes
Member

Some thoughts:

  • Since multiple organizers might be managing the same hackathon simultaneously, I think we need to account for conflicting updates. Maybe we could use a version number or last-updated timestamp to require confirmation before overwriting a newer change?
  • I think we should also distinguish between internal judging results and officially published results in the API since even after a track finishes judging, organizers might still need to verify the results before announcing winners. Perhaps have a separate publication status?
  • Also, might be useful to support bulk actions for organizers, like accepting/rejecting applicants or assigning judging, and have the API indicate which updates succeeded/failed/only some went through
Some thoughts: - Since multiple organizers might be managing the same hackathon simultaneously, I think we need to account for conflicting updates. Maybe we could use a version number or last-updated timestamp to require confirmation before overwriting a newer change? - I think we should also distinguish between internal judging results and officially published results in the API since even after a track finishes judging, organizers might still need to verify the results before announcing winners. Perhaps have a separate publication status? - Also, might be useful to support bulk actions for organizers, like accepting/rejecting applicants or assigning judging, and have the API indicate which updates succeeded/failed/only some went through
Member

@ipae wrote in #24 (comment):

  • Since multiple organizers might be managing the same hackathon simultaneously, I think we need to account for conflicting updates. Maybe we could use a version number or last-updated timestamp to require confirmation before overwriting a newer change?

Unlikely to be that often of an issue except for a few day-of things. Last-updated check with confirmation should be sufficient.

  • I think we should also distinguish between internal judging results and officially published results in the API since even after a track finishes judging, organizers might still need to verify the results before announcing winners. Perhaps have a separate publication status?

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.

  • Also, might be useful to support bulk actions for organizers, like accepting/rejecting applicants or assigning judging, and have the API indicate which updates succeeded/failed/only some went through

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.

@ipae wrote in https://git.cmu.dev/ScottyLabs/terrier/pulls/24#issuecomment-20164: > * Since multiple organizers might be managing the same hackathon simultaneously, I think we need to account for conflicting updates. Maybe we could use a version number or last-updated timestamp to require confirmation before overwriting a newer change? Unlikely to be that often of an issue except for a few day-of things. Last-updated check with confirmation should be sufficient. > * I think we should also distinguish between internal judging results and officially published results in the API since even after a track finishes judging, organizers might still need to verify the results before announcing winners. Perhaps have a separate publication status? 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. > * Also, might be useful to support bulk actions for organizers, like accepting/rejecting applicants or assigning judging, and have the API indicate which updates succeeded/failed/only some went through 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](https://github.com/ScottyLabs/chihuahua/blob/86ace96565e8a189019bfc224d1859d165173e3d/FLOW.md) 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.
Member

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?"

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?"
Member

Some thoughts on open question 9:

  • I think details such as aggregate scores, raw evaluations and rankings should be up to the global admin to decide to allow for more flexibility.
  • Another feature that may be useful is how the admin can publish the respective results for each team with fields like above for them to see. It could be an option to provide more info about the performance of each team without making the whole results page public.

On open question 6:

  • I think that an option for allowing withdrawals and edit should be a permission that is granted by the team leader. It could also be similar to github where requests are made by team members then may or may not be approved by the team leader/other members with permissions.
Some thoughts on open question 9: - I think details such as aggregate scores, raw evaluations and rankings should be up to the global admin to decide to allow for more flexibility. - Another feature that may be useful is how the admin can publish the respective results for each team with fields like above for them to see. It could be an option to provide more info about the performance of each team without making the whole results page public. On open question 6: - I think that an option for allowing withdrawals and edit should be a permission that is granted by the team leader. It could also be similar to github where requests are made by team members then may or may not be approved by the team leader/other members with permissions.
@ -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 |
Member

Should this deactive the hackathon first then delete after a certain amount of time in case it needs to be reversed?

Should this deactive the hackathon first then delete after a certain amount of time in case it needs to be reversed?
Owner

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 deleted flag and never truly delete data

because 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

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 `deleted` flag and never truly delete data because 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 @@
### Architecture
The 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`.
Owner

to be consistent with o-quest and the future maps mobile app, terrier should use capacitor, not tauri

to be consistent with o-quest and the future maps mobile app, terrier should use capacitor, not tauri
@ -0,0 +265,4 @@
### Offline Connectivity
Terrier 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.
Owner

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)

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.
Owner

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

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.
Owner

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

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
Member

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.

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.
All checks were successful
kennel/build build succeeded
kennel/deploy deployment healthy
nixbot/nix-eval evaluation succeeded in 0s (1 warning)
nixbot/nix-build 0 attributes built
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin rfc/0011-api-architecture:rfc/0011-api-architecture
git switch rfc/0011-api-architecture
Sign in to join this conversation.
No description provided.