diff --git a/db/schema/schema.surql b/db/schema/schema.surql
index 8a73c6c179ed1915db7a3627bf126c1ffdbfe680..3e4e55d7fda1ed1c603888948cf7cf000e62bf91 100644
--- a/db/schema/schema.surql
+++ b/db/schema/schema.surql
@@ -57,25 +57,59 @@ DEFINE FIELD final ON evaluation TYPE bool DEFAULT false PERMISSIONS FULL;
 -- NOTE: making this an edge between evaluation->submission seems overkill
 -- NOTE: but maybe make this a record reference? (https://surrealdb.com/docs/surrealql/datamodel/references)
 -- DEFINE FIELD annotations ON evaluation TYPE array<record<annotation>> DEFAULT [] PERMISSIONS FULL; 
-DEFINE FIELD annotations ON evaluation TYPE array<object> DEFAULT [] PERMISSIONS FULL;
+-- DEFINE FIELD annotations ON evaluation TYPE array<record<annotation>> DEFAULT [] PERMISSIONS FULL;
+
+DEFINE FIELD maxScore ON evaluation READONLY VALUE out.out.full_score PERMISSIONS FULL;
+DEFINE FIELD postDeltaScore ON evaluation READONLY VALUE <future> {
+	LET $scoreSum: float = <-annotation[WHERE $this.meta.scoreDelta].meta.scoreDelta.fold(0, |$a: any, $b: any| $a + $b);
+
+	LET $meta = IF $scoreSum < 0
+		{ {
+			reason: 'Negative',
+			valid: false
+		} }
+	ELSE IF $scoreSum > maxScore
+		{ {
+			reason: string::concat('Too high (max: ', ' ', maxScore, ')'),
+			valid: false
+		} }
+	ELSE
+		{ {
+			valid: true
+		} }
+	;
+	RETURN {
+		meta: $meta,
+		score: $scoreSum 
+	};
+}
+	PERMISSIONS FULL
+;
 
 DEFINE INDEX one_per_submission ON evaluation FIELDS out UNIQUE;
 
--- DEFINE EVENT ...
-
+-- TODO scoreDelta event
+-- NOTE: it might be better to just have a future which calculates after-score-delta score?
+-- DEFINE EVENT OVERWRITE annotationsChanged ON evaluation WHEN $before.annotations != $after.annotations THEN {
+--     LET $beforeScoreDelta = $before.annotations[? $this.meta.scoreDelta].meta.scoreDelta.fold(0, |$a, $b| $a + $b);
+--    LET $afterScoreDelta = $after.annotations[? $this.meta.scoreDelta].meta.scoreDelta.fold(0, |$a, $b| $a + $b);
+    -- TODO check that score + scoreDelta is within bounds!
+--	CREATE log SET time = time::now(), beforeScoreDelta = $beforeScoreDelta, afterScoreDelta = $afterScoreDelta;
+--};
 
 -- ------------------------------
 -- TABLE: annotation
 -- ------------------------------
 
--- DEFINE TABLE annotation TYPE NORMAL SCHEMALESS PERMISSIONS NONE;
--- DEFINE FIELD color ON annotation TYPE option<string> PERMISSIONS FULL;
--- DEFINE FIELD content ON annotation TYPE string PERMISSIONS FULL;
--- TODO data schema for position
--- * can apply to a range (or ranges?) in the text source of the submission, shown at the range it applies to, OR
--- * can apply to the submission as a whole, shown in a dedicated window/list/view on the submission
--- DEFINE FIELD 
+DEFINE TABLE annotation TYPE RELATION IN tutor | reviewer OUT evaluation SCHEMALESS PERMISSIONS NONE;
+DEFINE FIELD type ON annotation TYPE "document" | "line" | "range" PERMISSIONS FULL;
+DEFINE FIELD content ON annotation TYPE string PERMISSIONS FULL;
+
+-- DEFINE FIELD meta.author ON annotation TYPE record<tutor> PERMISSIONS FULL;
+DEFINE FIELD meta.scoreDelta ON annotation TYPE option<float>  PERMISSIONS FULL;
 
+DEFINE FIELD time.created_at ON annotation TYPE datetime DEFAULT time::now() PERMISSIONS FULL;
+DEFINE FIELD time.updated_at ON annotation TYPE datetime VALUE time::now() PERMISSIONS FULL;
 
 -- ------------------------------
 -- TABLE: exercise_group