Ë
    ÛJêj 0  ã                  ó‚   — U d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	mZ ddl
mZ dd	d
dœZded<    G d„ d«      ZdgZy)zGSQLite storage foundation with versioned schema and explicit retention.é    )ÚannotationsN)ÚIterator)Úcontextmanager)ÚUTCÚdatetime)ÚPath)a‹  
        CREATE TABLE tasks (
            task_id TEXT PRIMARY KEY,
            handler TEXT NOT NULL,
            payload_json TEXT NOT NULL,
            status TEXT NOT NULL,
            result_json TEXT,
            error TEXT,
            attempts INTEGER NOT NULL DEFAULT 0,
            created_at REAL NOT NULL,
            started_at REAL,
            completed_at REAL
        )
        zBCREATE INDEX tasks_status_created_idx ON tasks(status, created_at)aü  
        CREATE TABLE approval_requests (
            request_id TEXT PRIMARY KEY,
            agent_json TEXT NOT NULL,
            action TEXT NOT NULL,
            resource TEXT,
            context_json TEXT NOT NULL,
            risk_score REAL NOT NULL,
            status TEXT NOT NULL,
            created_at REAL NOT NULL,
            reviewed_at REAL,
            reviewer TEXT,
            reason TEXT NOT NULL,
            decision TEXT,
            metadata_json TEXT NOT NULL
        )
        zRCREATE INDEX approvals_status_created_idx ON approval_requests(status, created_at)aŽ  
        CREATE TABLE approval_records (
            request_id TEXT PRIMARY KEY REFERENCES approval_requests(request_id) ON DELETE CASCADE,
            agent_id TEXT NOT NULL,
            action TEXT NOT NULL,
            resource TEXT,
            decision TEXT NOT NULL,
            reviewer TEXT NOT NULL,
            timestamp REAL NOT NULL,
            reason TEXT NOT NULL
        )
        aH  
        CREATE TABLE audit_events (
            event_id TEXT PRIMARY KEY,
            event_type TEXT NOT NULL,
            timestamp REAL NOT NULL,
            actor TEXT NOT NULL,
            agent_id TEXT NOT NULL,
            task_id TEXT NOT NULL,
            model TEXT NOT NULL,
            tool TEXT NOT NULL,
            action TEXT NOT NULL,
            resource TEXT NOT NULL,
            policy_decision TEXT NOT NULL,
            approval_id TEXT NOT NULL,
            result TEXT NOT NULL,
            error TEXT NOT NULL,
            resource_usage_json TEXT NOT NULL,
            latency_ms REAL NOT NULL,
            network_action TEXT NOT NULL,
            memory_write TEXT NOT NULL,
            security_alert TEXT NOT NULL,
            metadata_json TEXT NOT NULL,
            status TEXT NOT NULL
        )
        zDCREATE INDEX audit_task_time_idx ON audit_events(task_id, timestamp)zGCREATE INDEX audit_type_time_idx ON audit_events(event_type, timestamp)a^  
        CREATE TABLE project_memories (
            memory_id TEXT PRIMARY KEY,
            project_id TEXT NOT NULL,
            content TEXT NOT NULL,
            trust_level TEXT NOT NULL,
            provenance_id TEXT,
            metadata_json TEXT NOT NULL,
            created_at REAL NOT NULL,
            expires_at REAL
        )
        zRCREATE INDEX memories_project_time_idx ON project_memories(project_id, created_at)z@CREATE INDEX memories_trust_idx ON project_memories(trust_level)aF  
        CREATE TABLE provenance_records (
            content_id TEXT PRIMARY KEY,
            content_json TEXT NOT NULL,
            sha256 TEXT NOT NULL,
            metadata_json TEXT NOT NULL,
            labels_json TEXT NOT NULL,
            watermark_json TEXT,
            created_at REAL NOT NULL
        )
        zŠ
        CREATE TABLE schema_migrations (
            version INTEGER PRIMARY KEY,
            applied_at TEXT NOT NULL
        )
        )a  
        CREATE TABLE knowledge_documents (
            document_id TEXT PRIMARY KEY,
            source_id TEXT NOT NULL,
            source_uri TEXT NOT NULL,
            content_sha256 TEXT NOT NULL,
            media_type TEXT NOT NULL,
            trust_level TEXT NOT NULL,
            sensitivity TEXT NOT NULL,
            status TEXT NOT NULL,
            metadata_json TEXT NOT NULL,
            created_at REAL NOT NULL,
            updated_at REAL NOT NULL,
            UNIQUE(source_id, content_sha256)
        )
        zYCREATE INDEX knowledge_documents_source_idx ON knowledge_documents(source_id, updated_at)zVCREATE INDEX knowledge_documents_status_idx ON knowledge_documents(status, updated_at))z/ALTER TABLE audit_events ADD COLUMN seq INTEGERz2ALTER TABLE audit_events ADD COLUMN prev_hash TEXTz3ALTER TABLE audit_events ADD COLUMN entry_hash TEXTz1CREATE INDEX audit_chain_idx ON audit_events(seq))é   é   é   zdict[int, tuple[str, ...]]Ú_MIGRATIONSc                  óˆ   — e Zd ZdZ ee«      Zddœdd„Zedd„«       Z	edd„«       Z
dd„Zdd„Zdd	„Zd
dœdd„Zdd„Zdd„Zy
)ÚSQLiteDatabaseaG  Local SQLite database shared by durable control-plane repositories.

    The database is created with owner-only file permissions where supported.
    Retention is explicit: callers invoke :meth:`prune_expired` from a
    deployment scheduler or maintenance command rather than deleting records
    on application startup.
    éZ   )Úretention_daysc               ó  — |dk  rt        d«      ‚t        |«      }|dk(  s|j                  d«      rt        d«      ‚t        |«      j	                  «       j                  «       | _        || _        | j                  j                  j                  «       }| j                  j                  j                  ddd¬«       |s&	 | j                  j                  j                  d«       | j                  «        y # t        $ r Y Œw xY w)	Nr   zretention_days must be positivez:memory:zfile:z.SQLiteDatabase requires a persistent file pathTéÀ  ©ÚparentsÚexist_okÚmode)Ú
ValueErrorÚstrÚ
startswithr   Ú
expanduserÚresolveÚpathr   ÚparentÚexistsÚmkdirÚchmodÚOSErrorÚ_initialize)Úselfr   r   Ú	path_textÚparent_existeds        úJ/home/oem/CyberBrain26-unified/src/cyberbrain26/data_plane/sqlite_store.pyÚ__init__zSQLiteDatabase.__init__¡   sà   € Ø˜QÒÜÐ>Ó?Ð?Ü˜“Iˆ	Ø˜
Ò" i×&:Ñ&:¸7Ô&Cô
 ÐMÓNÐNÜ˜“J×)Ñ)Ó+×3Ñ3Ó5ˆŒ	Ø,ˆÔØŸ™×)Ñ)×0Ñ0Ó2ˆØ�	‰	×Ñ×Ñ t°dÀÐÔGÙðØ—	‘	× Ñ ×&Ñ& uÔ-ð 	×ÑÕøô ò Ùðús   Â?%C5 Ã5	DÄ Dc              #  ó4  K  — t        j                  | j                  dd¬«      }t         j                  |_        |j                  d«       |j                  d«       |j                  d«       	 |–— |j                  «        y# |j                  «        w xY w­w)z<Yield a configured connection and always close it afterward.g      @N)ÚtimeoutÚisolation_levelzPRAGMA foreign_keys = ONzPRAGMA busy_timeout = 5000úPRAGMA synchronous = FULL)Úsqlite3Úconnectr   ÚRowÚrow_factoryÚexecuteÚclose©r#   Ú
connections     r&   r3   zSQLiteDatabase.connection¶   sz   è ø€ ô —_‘_ T§Y¡Y¸ÈTÔRˆ
Ü!(§¡ˆ
ÔØ×ÑÐ5Ô6Ø×ÑÐ7Ô8Ø×ÑÐ6Ô7ð	ØÒà×ÑÕøˆJ×ÑÕüs   ‚A+BÁ.B Á2BÂBÂBc              #  ó   K  — | j                  «       5 }|j                  d«       	 |–— |j                  «        | j                  «        	 ddd«       y# t        $ r |j                  «        ‚ w xY w# 1 sw Y   yxY w­w)z3Yield a write transaction with rollback on failure.zBEGIN IMMEDIATEN)r3   r0   ÚcommitÚ_restrict_file_permissionsÚBaseExceptionÚrollbackr2   s     r&   ÚtransactionzSQLiteDatabase.transactionÃ   s�   è ø€ ð �_‰_Óð 		2 *Ø×ÑÐ0Ô1ð2Ø Ò ð
 ×!Ñ!Ô#Ø×/Ñ/Õ1÷		2ð 		2øô !ò Ø×#Ñ#Ô%Øðú÷			2ð 		2üs2   ‚A>“A2¦Aª A2Á	A>ÁA/Á/A2Á2A;Á7A>c                ó¸  — t        |«      j                  «       j                  «       }|j                  j	                  ddd¬«       | j                  «       5 }t        j                  |«      }	 |j                  |«       |j                  «        	 ddd«       	 |j                  d«       |S # |j                  «        w xY w# 1 sw Y   Œ2xY w# t        $ r Y |S w xY w)z>Create a consistent SQLite backup using the online backup API.Tr   r   Né€  )r   r   r   r   r   r3   r,   r-   Úbackupr1   r    r!   )r#   ÚdestinationÚtargetÚsourcer<   s        r&   r<   zSQLiteDatabase.backupÑ   s½   € ä�kÓ"×-Ñ-Ó/×7Ñ7Ó9ˆØ�‰×Ñ D°4¸eÐÔDØ�_‰_Óð 	 &Ü—_‘_ VÓ,ˆFðØ—‘˜fÔ%à—‘•÷	ð	Ø�L‰L˜Ôð ˆøð —‘•ú÷	ð 	ûô ò 	ØØˆð	ús6   ÁC Á-B+Á>C ÂC Â+B=Â=C Ã C	Ã	CÃCc                óp   — | j                  «       5 }|j                  d«       ddd«       y# 1 sw Y   yxY w)z@Checkpoint the WAL so the main database contains committed data.zPRAGMA wal_checkpoint(TRUNCATE)N)r3   r0   r2   s     r&   Ú
checkpointzSQLiteDatabase.checkpointá   s6   € à�_‰_Óð 	B *Ø×ÑÐ@ÔA÷	B÷ 	Bñ 	Bús   ‘,¬5c                óª   — | j                  «       5 }|j                  d|f«      j                  «       }ddd«       t        d   «      S # 1 sw Y   ŒxY w)ur  Count audit records older than ``cutoff``.

        Split out from :meth:`prune_expired` so the caller can inspect the chain
        *before* the evidence is removed. Retention is a deadline and must not be
        refused because the chain is broken â€” but whether it is broken has to be
        known first, otherwise the purge cannot record what it removed.
        z:SELECT COUNT(*) AS n FROM audit_events WHERE timestamp < ?NÚn)r3   r0   ÚfetchoneÚint)r#   Úcutoffr3   Úrows       r&   Úcount_audit_beforez!SQLiteDatabase.count_audit_beforeæ   sY   € ð �_‰_Óð 	 *Ø×$Ñ$ØLØ�	ó÷ ‰h‹jð ÷	ô
 �3�s‘8‹}Ð÷	ð 	ús   ‘"A	Á	AN)Únowc               óÄ  — |€'t        j                  t        «      j                  «       }|| j                  dz  dz  dz  z
  }| j                  «       5 }|j                  d|f«      j                  }|j                  d|f«      j                  }|j                  d|f«      j                  }|j                  d|f«      j                  }ddd«       dœS # 1 sw Y   ŒxY w)	ax  Apply the configured retention window to terminal records.

        Pending approval requests and unfinished tasks are never removed.
        Completed/failed tasks, decided approvals, and audit events older than
        the cutoff are deleted. This operation is explicit and auditable by the
        caller; SQLite does not securely erase old pages or WAL fragments.
        Né   é<   zkDELETE FROM tasks WHERE status IN ('completed', 'failed') AND completed_at IS NOT NULL AND completed_at < ?zoDELETE FROM approval_requests WHERE status IN ('approved', 'denied', 'expired', 'cancelled') AND created_at < ?z,DELETE FROM audit_events WHERE timestamp < ?zMDELETE FROM project_memories WHERE expires_at IS NOT NULL AND expires_at <= ?)ÚtasksÚ	approvalsÚaudit_eventsÚproject_memories)r   rI   r   Ú	timestampr   r9   r0   Úrowcount)r#   rI   rF   r3   rM   rN   ÚauditÚmemoriess           r&   Úprune_expiredzSQLiteDatabase.prune_expiredõ   s  € ð ˆ;Ü—,‘,œsÓ#×-Ñ-Ó/ˆCØ�t×*Ñ*¨RÑ/°"Ñ4°rÑ9Ñ9ˆØ×ÑÓð 	 :Ø×&Ñ&ðDà�	ó÷ ‰hð	 ð
 #×*Ñ*ðTà�	ó÷ ‰hð	 ð
 ×&Ñ&Ø>ÀÀ	óç‰hð ð "×)Ñ)Ø_Ø�ó÷ ‰hð ÷	ð& Ø"Ø!Ø (ñ	
ð 	
÷%	ð 	ús   ÁA5CÃCc           	     ó4  — | j                  «       5 }|j                  d«       |j                  d«       t        |j                  d«      j                  «       d   «      }|| j                  kD  rt        d|› d| j                  › �«      ‚t        |dz   | j                  dz   «      D ]®  }t        j                  |«      }|€t        d|› �«      ‚|j                  d	«       	 |D ]  }|j                  |«       Œ |j                  d
|t        j                  t        «      j                  «       f«       |j                  d|› �«       |j                  «        Œ° 	 d d d «       | j!                  «        y # t        $ r |j                  «        ‚ w xY w# 1 sw Y   Œ8xY w)NzPRAGMA journal_mode = WALr+   zPRAGMA user_versionr   zdatabase schema z  is newer than supported schema r	   zmissing SQLite migration zBEGIN EXCLUSIVEz@INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)zPRAGMA user_version = )r3   r0   rE   rD   ÚCURRENT_SCHEMA_VERSIONÚRuntimeErrorÚranger   Úgetr   rI   r   Ú	isoformatr5   r7   r8   r6   )r#   r3   ÚcurrentÚversionÚ
statementsÚ	statements         r&   r"   zSQLiteDatabase._initialize  s—  € Ø�_‰_Óð 	 *Ø×ÑÐ:Ô;Ø×ÑÐ:Ô;Ü˜*×,Ñ,Ð-BÓC×LÑLÓNÈqÑQÓRˆGØ˜×4Ñ4Ò4Ü"Ø& w iÐ/OØ×2Ñ2Ð3ð5óð ô ! ¨1¡¨d×.IÑ.IÈAÑ.MÓNò �Ü(Ÿ_™_¨WÓ5�
ØÐ%Ü&Ð)BÀ7À)Ð'LÓMÐMØ×"Ñ"Ð#4Ô5ðØ%/ò 6˜	Ø"×*Ñ*¨9Õ5ð6à×&Ñ&ØZØ ¤(§,¡,¬sÓ"3×"=Ñ"=Ó"?Ð@ôð ×&Ñ&Ð)?À¸yÐ'IÔJØ×%Ñ%Õ'ñ÷	ð4 	×'Ñ'Õ)øô %ò Ø×'Ñ'Ô)Øðú÷/	ð 	ús%   ‘CFÃA5E0ÅFÅ0FÆFÆFc                óZ   — 	 | j                   j                  d«       y # t        $ r Y y w xY w)Nr;   )r   r    r!   )r#   s    r&   r6   z)SQLiteDatabase._restrict_file_permissions6  s)   € ð	Ø�I‰I�O‰O˜EÕ"øÜò 	Ùð	ús   ‚ ž	*©*)r   ú
str | Pathr   rE   ÚreturnÚNone)rb   zIterator[sqlite3.Connection])r=   ra   rb   r   )rb   rc   )rF   Úfloatrb   rE   )rI   zfloat | Nonerb   zdict[str, int])Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úmaxr   rW   r'   r   r3   r9   r<   rA   rH   rU   r"   r6   © ó    r&   r   r   –   si   „ ññ ! Ó-ÐàBDõ ð* ò
ó ð
ð ò2ó ð2óó Bó
ð 48õ "
óH*ô:rk   r   )rh   Ú
__future__r   r,   Úcollections.abcr   Ú
contextlibr   r   r   Úpathlibr   r   Ú__annotations__r   Ú__all__rj   rk   r&   ú<module>rr      sU   ðÚ Må "ã Ý $Ý %ß "Ý ðhðRð(	ñ}H+€Ð'ó H÷Vdñ dðN Ð
�rk   