ΖΩΝΤΑΝΑ · ΑΛΥΣΙΔΑ ΕΛΕΓΧΟΥ · ΕΕ
ΣΥΣΤΗΜΑ · 99,99% ΔΙΑΘΕΣΙΜΟΤΗΤΑ
v 1.0 ↗ ΦΤΙΑΓΜΕΝΟ ΣΤΗΝ ΕΕ

Έννοιες

Τι είναι πραγματικά μια συνεδρία, μια εγγραφή τεκμηρίου και μια αλυσίδα ελέγχου, με τις λιγότερες δυνατές λέξεις. Διαβάστε το μία φορά και η αναφορά API θα βγάλει νόημα.

Οργανισμός

Ο tenant ανώτατου επιπέδου. Ένας οργανισμός αντιστοιχεί σε έναν λογαριασμό πελάτη. Κάθε άλλος πόρος (συνεδρίες, τεκμήρια, συμβάντα ελέγχου, χρήστες) περιορίζεται σε έναν οργανισμό μέσω row-level security στους υποκείμενους πίνακες Postgres. Ένα σφάλμα στον κώδικα της εφαρμογής δεν μπορεί να διασχίσει tenant — η βάση δεδομένων θα απορρίψει το ερώτημα.

Ένας οργανισμός έχει: μέλη (χρήστες με πρόσβαση βάσει ρόλου), branding (λογότυπο / χρώματα / υποσέλιδο PDF), συνδρομή χρέωσης, προαιρετικά δεδομένα νομικής οντότητας KYB, προαιρετική διαμόρφωση SSO και πολιτική διατήρησης.

Μέλος, Ρόλος, Δικαίωμα

Ένα Ιδιότητα μέλους είναι η σύνδεση μεταξύ ενός χρήστη και ενός οργανισμού. Ένας χρήστης μπορεί να έχει ιδιότητα μέλους σε πολλαπλούς οργανισμούς και να εναλλάσσεται μεταξύ τους (ο ενεργός οργανισμός μεταφέρεται ως claim του JWT).

Κάθε οργανισμός αρχικοποιεί τέσσερις ρόλους συστήματος κατά τη δημιουργία:

  • org_admin — πλήρης έλεγχος. Χρέωση, μέλη, branding, διατήρηση.
  • inspector — μπορεί να εκτελεί επιθεωρήσεις, να καταγράφει τεκμήρια, να υπογράφει αναφορές.
  • observer — πρόσβαση μόνο για ανάγνωση σε συνεδρίες + δεδομένα ελέγχου.
  • auditor — πρόσβαση μόνο για ανάγνωση συν δικαίωμα επαλήθευσης αλυσίδας.

Οι διαχειριστές οργανισμού μπορούν να δημιουργήσουν προσαρμοσμένους ρόλους συνθέτοντας τον κατάλογο δικαιωμάτων. Τα δικαιώματα ελέγχονται ως slug στο επίπεδο view + διασταυρώνονται από το RLS στο επίπεδο DB.

Συνεδρία

Μία επιθεώρηση. Η μονάδα χρέωσης (πληρώνετε ανά κλεισμένη συνεδρία) και η μονάδα τεκμηρίων (μια αλυσίδα ελέγχου είναι ανά συνεδρία, όχι ανά οργανισμό).

Μια συνεδρία έχει: έναν χειριστή (το μέλος της ομάδας σας που την ξεκίνησε), έναν ή περισσότερους συμμετέχοντες (τον χρήστη πεδίου, συν προαιρετικούς παρατηρητές), κατάσταση συγκατάθεσης, προαιρετική θέση GPS, προαιρετικές σημειώσεις, μια αλυσίδα ελέγχου και — μόλις κλείσει — χρονοσφραγίδες αγκυρωμένες σε TSA.

Συμμετέχων

Ένα άτομο σε μια συνεδρία. Υπάρχει ένας χειριστής ανά συνεδρία και τουλάχιστον ένας χρήστης πεδίου· υποστηρίζονται προαιρετικοί πρόσθετοι παρατηρητές. Οι χρήστες πεδίου συνδέονται μέσω ενός υπογεγραμμένου URL μίας χρήσης (δεν απαιτείται λογαριασμός)· οι χειριστές + παρατηρητές είναι μέλη του οργανισμού.

Τεκμήρια

Ένα κομμάτι καταγεγραμμένης απόδειξης κατά τη διάρκεια μιας συνεδρίας. Είδη:

  • snapshot — ακίνητη φωτογραφία από την κάμερα του χρήστη πεδίου.
  • annotation — σχέδιο επικαλυπτόμενο σε ένα στιγμιότυπο ή πίνακα ζωγραφικής.
  • whiteboard — καμβάς Excalidraw εντός συνεδρίας, εξαγόμενος ως PNG + κατάσταση.
  • clip — σύντομο τμήμα βίντεο.
  • document — μεταφορτωμένο αρχείο (χρησιμοποιείται από το επίπεδο συνομιλίας για PDF προς υπογραφή).

Κάθε εγγραφή τεκμηρίου έχει ένα SHA-256 του δυαδικού της περιεχομένου, αποθηκευμένο στην αλυσίδα ελέγχου. Η παραποίηση του αρχείου εκ των υστέρων αποτυγχάνει στην επαλήθευση.

Αλυσίδα ελέγχου

Η κρυπτογραφική ραχοκοκαλιά. Κάθε συμβάν σε μια συνεδρία — δημιουργία συνεδρίας, παραχώρηση συγκατάθεσης, καταγραφή GPS, καταγραφή τεκμηρίου, σχολιασμός, αποθήκευση πίνακα ζωγραφικής, υπογραφή, λήξη συνεδρίας — εκπέμπει μια AuditEvent εγγραφή με:

{
  "session": "<uuid>",
  "sequence": N,
  "occurred_at": "<iso8601>",
  "kind": "evidence.snapshot_added",
  "actor": { "user": <id|null>, "participant": <id|null> },
  "payload": { /* event-specific */ },
  "prev_hash": "<sha256 of previous event>",
  "hash": "<sha256 of canonical_json of this event>"
}

Το πρώτο συμβάν χρησιμοποιεί prev_hash = "0" * 64 (genesis). Κάθε επόμενο συμβάν χρησιμοποιεί το hash του προηγούμενου συμβάντος ως prev_hash και αυξάνει το sequence κατά 1. Ένα advisory lock της Postgres σειριοποιεί τις εγγραφές ανά συνεδρία· ένα append-only trigger μπλοκάρει UPDATE + DELETE στον πίνακα.

TimestampToken (αγκύρωση TSA)

Στη λήξη της συνεδρίας (και κατά το «stamp now» που ενεργοποιεί ο χειριστής), η τρέχουσα κεφαλή αλυσίδας υποβάλλεται σε τρεις ανεξάρτητες αρχές χρονοσφραγίδας:

  • YodaLedger — Αγκύρωση στο blockchain Tezos. Οριστικοποίηση ~15-20 λεπτά. Ασύγχρονη· λαμβάνουμε ένα callback όταν επιβεβαιωθεί το μπλοκ.
  • FreeTSA — Χρονοσφραγίδα RFC 3161. Σύγχρονη· το token επιστρέφεται άμεσα. Εναλλάξιμη με έναν επί πληρωμή QTSP (DataSure) για συμμόρφωση με το eIDAS Άρθρο 42.
  • OpenTimestamps — Αγκύρωση στο Bitcoin μέσω του πρωτοκόλλου ημερολογίου OpenTimestamps. Ασύγχρονη· η διαδρομή αναβάθμισης εκτελείται σε ένα Celery sweep.

Το τρία είναι σχεδιαστική επιλογή — αν κάποια από τις TSA εξαφανιστεί, οι άλλες δύο εξακολουθούν να αγκυρώνουν την αλυσίδα. Ένας ελεγκτής μπορεί να επαληθεύσει έναντι οποιασδήποτε από αυτές ανεξάρτητα, χρησιμοποιώντας δημόσιους block explorers / endpoints επαλήθευσης.

Υπογραφή (SES / AES / QES)

Τρία επίπεδα eIDAS, όλα στο ίδιο PDF αναφοράς ελέγχου:

  • SES (Απλή Ηλεκτρονική Υπογραφή) — υποστηριζόμενη από αλυσίδα ελέγχου, χωρίς πιστοποιητικό υπογραφής. Κατάλληλη για εσωτερικά αρχεία.
  • AES (Προηγμένη Ηλεκτρονική Υπογραφή) — πιστοποιητικό υπογραφής συνδεδεμένο με ταυτότητα, αγκυρωμένο κατά PAdES B-T. Κατάλληλη για τα περισσότερα συμβόλαια B2B.
  • QES (Εγκεκριμένη Ηλεκτρονική Υπογραφή) — το ανώτατο επίπεδο eIDAS, νομικά ισοδύναμο με ιδιόχειρη υπογραφή σε όλη την ΕΕ. Περιορισμένο πίσω από επαλήθευση KYB του εκδίδοντος οργανισμού.

Καμπάνια (προαιρετικά)

Μια λογική ομαδοποίηση συνεδριών για ομαδική αναφορά — «Απαιτήσεις αυτοκινήτων Q2 2026» ή «Ελαττώματα παράδοσης Χώρου A». Οι συνεδρίες δεν απαιτούν καμπάνια· είναι μια διευκόλυνση αναφοράς.

Webhook

Ένα URL καταχωρημένο από τον πελάτη που λαμβάνει POST συμβάντων υπογεγραμμένα με HMAC. Τύποι συμβάντων: session.created, session.completed, participant.joined, participant.left, evidence.added, recording.ready, audit.anchored, signature.completed, συν ένα webhook.test για επαλήθευση παράδοσης.

Υπογραφή: τύπου Stripe t=...,v1=... header με HMAC-SHA256 πάνω σε <timestamp>.<body>. Ο βοηθός constructEvent() του SDK επαληθεύει σε σταθερό χρόνο με ανοχή απόκλισης ρολογιού 5 λεπτών.