Architektúra áttekintés¶
A Cadrumo egy helyi-elsődleges alkalmazás, amely spanyol adóbevallásokat készít elő az aeat parancssori felületen keresztül. Modellezi az adóhatóság szabályozási registryjét, beolvassa és besorolja az Ön pénzügyi nyilvántartásait, és kiszámítja az egyes adóűrlapok számozott rovatait. Ezután ellenőrzi a borradort, és exportál egy fájlt, amelyet Ön maga nyújt be. Az AEAT az Agencia Estatal de Administración Tributaria, Spanyolország adóhivatala.
Használja ezt az oldalt belépési pontként, amikor először olvassa a kódbázist. Ez egy térkép, nem egy címtár: megnevezi a rétegeket, a teherhordó fogalmakat és a kanonikus típusokat, amelyekhez navigálni fog, és ott meg is áll. A pontos szignatúrákért és parancsokért kövesse a Belépés a kódba szakaszban lévő hivatkozásokat.
Miért ilyen felépítésű a rendszer¶
Egy spanyol adóbevallás kézi elkészítése hibalehetőségekkel teli és nehezen auditálható. Egy űrlapon szereplő adatnak vissza kell vezethetőnek lennie egy bankmozgásra, egy szabályozásra és egy közzétett szabályra. Egy későbbi éves űrlapnak összhangban kell maradnia az őt tápláló negyedéves űrlapokkal. Három tervezési döntés válaszol erre a problémára, és ezek alakítanak mindent mást:
Helyi-elsődleges. Az Ön pénzügyi nyilvántartásai soha nem hagyják el a gépét. Az eszköz offline fut, és titkosított adatcsomagokat tárol egy helyi, lemezen lévő adatbázisban.
A registry a tekintély. Az adószabályok - kulcsok, sávok, határidők és az egyes rovatok jogalapja - nincsenek kódba égetve. Adatként vannak megírva, lefordítva, validálva, és egyetlen tekintélyen keresztül olvasva. Egy adat mindig visszavezethető a szabályra, amely előállította.
Az ember nyújt be, nem az eszköz. A feldolgozási folyamat egy exportfájlnál ér véget. Ennek a hatósághoz való benyújtása szándékos emberi lépés. Az eszköznek egyáltalán nincs benyújtási útvonala, így az élő benyújtás nem védett, hanem egyszerűen hiányzik.
Az ebből következő szerkezet hexagonális: az üzleti szabályok a középpontban helyezkednek el, a külvilággal érintkező elemzők, böngészők és tárolók pedig a peremen. A legtöbb függőség befelé mutat. Az alkalmazás-összeállításnak van egy kifejezett, ellenőrzött kivétele, amely eléri az adaptereket. Ez az adólogikát önmagában tesztelhetővé teszi, és lehetővé teszi egy adapter megváltoztatását anélkül, hogy egy szabályhoz kellene nyúlni.
Hogyan olvassa ezt az oldalt¶
Négy nézet fedi le a rendszert a legmagasabb szinten. Mindegyik egy ábrát párosít egy rövid magyarázattal:
A rétegek - az öt hexagonális réteg, és hogy mindegyik miért felel.
A registry-tekintély feldolgozási folyamata - hogyan válik az adószabály-adatokból az a pillanatkép, amelyet a futásidejű kód beolvas.
A modelo életciklusa - az út a nyilvántartásoktól egy exportfájlig, és hogy minden egyes adat hogyan van megalapozva.
A perzisztencia és a biztonsági határ - hol él az állapot, és miért nem hagy el semmi.
A rétegek¶
A Cadrumo öt rétegre osztja a felelősségeket a src/cadrumo/ alatt. A rétegek általában csak a náluk beljebb lévő rétegektől függnek; az alkalmazás-összeállításnak van a dokumentált adapterkivétele.
flowchart TD
EP["entrypoints — CLI (config · app)"]
AD["adapters — inbound · outbound · persistence"]
APP["application — use-case services"]
DOM["domain — tax rules and entities"]
CORE["core — enums · JavaScript Object Notation (JSON) contract · config · primitives"]
EP --> APP
EP --> CORE
APP --> DOM
APP --> AD
APP --> CORE
AD --> DOM
AD --> CORE
DOM --> CORE
DOM -.->|"secure-repo seam"| AD
Szöveges alternatíva. A belépési pontok az application és a core réteget hívják. Az application a domain, az adapters és a core réteget hívja; az adapters a domaint és a core-t hívja; a domain pedig a core-t hívja. A domain csak a megjelölt, biztonságos tárolóvarraton keresztül éri el az adaptereket.
A
corea legbelső réteg. Ez birtokolja azokat a keresztmetsző primitíveket, amelyeken minden más réteg osztozik. Típusos felsorolásai zárt értékkészleteket határoznak meg, például időszakkódokat, adódoméneket, modelo-azonosítókat és binding-forrástípusokat. A core birtokolja továbbá a JSON-boríték szerződését, a konfigurációt, a pénz- és időtípusokat, valamint a hibataxonómiát.A
domaintiszta adószabályokat és -nyilvántartásokat tartalmaz: a modelo registryt, a casilla-definíciókat (a casilla egy űrlap egy számozott rovata), a benyújtási megfigyeléseket, és a rájuk épülő számításokat. Csak acore-tól függ.Az
applicationhangolja össze a felhasználási eseteket. A domain szabályait adapterekkel köti össze, hogy benyújtási borradorokat építsen, aggregálja a ledgert, diagnosztikát futtasson és állapotot vetítsen. Saját maga nem végez sem bemenetet, sem kimenetet.Az
adaptershárom részben köti össze az alkalmazást a külvilággal. Azinbounda beérkező Portable Document Format (PDF), vesszővel elválasztott értékek (CSV), Open Financial Exchange (OFX) és Microsoft Excel Open XML (XLSX) kivonatokat elemzi. Azoutboundkülső szolgáltatásokat ér el (AEAT-böngészőmenetek, számítási orákulumok és hitelesítési szolgáltatók). Apersistencetitkosított adatcsomagokat tárol a helyi adatbázisban.Az
entrypointsteszi elérhetővé az alkalmazást a kezelők számára. A parancssor itt él, és gyökérfelülete két parancscsaládra korlátozódik:configésapp.
Két határszabály tartja tisztán a rétegeket. A határon áthaladó adatok validált pydantic v2 modellként lépnek át, soha nem laza szótárként. A zárt értékkészletek típusos felsorolásként vannak deklarálva a core-ban, és felsorolástagként áramlanak, így egy érvénytelen érték elutasításra kerül a határon.
A függőségi nyilak befelé mutatnak, egyetlen megjelölt kivétellel. Három domain-tároló - filing, justificante és submission - közvetlenül a titkosított tárolás alaposztályára épül az adapters.persistence-ben. Az ábra ezt a varratot szaggatott élként rajzolja meg, ahelyett, hogy elrejtené.
A domain-en és az application-ön belül az alcsomagok öt fogalmi csoportba rendeződnek. Néhány alcsomagot az áttekinthetőség kedvéért kihagytunk; az API-referencia mindet felsorolja.
Csoport |
|
|
|---|---|---|
Registry és számítások |
Az alábbi alcsomagok: |
Az alábbi alcsomagok: |
Ledger és tranzakciók |
Az alábbi alcsomagok: |
Az alábbi alcsomagok: |
Benyújtás és export |
Az alábbi alcsomagok: |
Az alábbi alcsomagok: |
Live, portálok és hitelesítés |
Az alábbi alcsomagok: |
Az alábbi alcsomagok: |
Profil és tárolás |
Az alábbi alcsomagok: |
Az alábbi alcsomagok: |
A modelo életciklusa¶
A modelo egy számozott AEAT-adóűrlap. Adatai egy irányba áramlanak, az Ön nyilvántartásaitól egy fájlig, amelyet Ön maga tölt fel.
flowchart LR
REC["Financial records — statements · invoices · evidence"]
ING["Ingest and classify — transactions · invoices · evidence"]
LED["Ledger / aggregation substrate — encrypted bucket · resolver mesh"]
CRE["work create"]
CAL["calculate — produces CalculationRevision (casillas)"]
VER["verify — completeness gate"]
FIL["file — local final marker"]
EXP["export — fichero-BOE file on disk"]
HUM{{"Human upload at AEAT sede — outside the tool"}}
AEAT["AEAT"]
REC --> ING --> LED
CRE --> CAL
LED --> CAL
CAL --> VER
VER --> FIL
VER --> EXP
FIL --> EXP
EXP --> HUM
HUM -.->|"manual submission"| AEAT
Szöveges alternatíva. A pénzügyi nyilvántartások beolvasásra és besorolásra kerülnek a titkosított ledgerbe. A kezelő létrehoz egy munkát, kiszámítja, ellenőrzi, helyileg benyújtottként megjelöli, és exportál egy fájlt. Egy ember ezután feltölti ezt a fájlt az AEAT-hoz, a Cadrumón kívül.
Az eszköz beolvassa és besorolja a pénzügyi nyilvántartásokat - bankkivonatokat, számlákat és azok bizonyítékait - a titkosított ledgerbe. Innen az út a parancssori igék rögzített sorozatát követi:
Az
aeat app modelo work createegy benyújtást egy modelóhoz, évhez és időszakhoz rögzít.A
calculatefeloldja az összes casillát, és elment egyCalculationRevision-t.A
verifyteljességi és konzisztencia-kaput futtat a borrador felett.A
fileegy ellenőrzött revíziót belsőleg benyújtottként jelöl meg.Az
aeat app modelo exporta hivatalos feltöltési fájlt (egy rögzített elrendezésű fichero-BOE artefaktumot) írja a lemezre.
A határ szerkezeti. A file egy helyi jelölés, nem benyújtás, az export pedig egy fájlt ír az Ön lemezére. Egyetlen parancs sem továbbít semmit a hatóságnak: a feltöltés emberi cselekvés az AEAT-portálon, amelyet az eszköz határán túli lépésként modellezünk. A kezelői élő olvasások a szokásos hitelesítést és az aktív profil védelmét igénylik; csak olvashatók maradnak. A külön CADRUMO_LIVE_TESTS_ENABLED opt-in kapuzza a fejlesztői élő olvasási teszteket.
Hogyan van megalapozva egy adat¶
Egy casilla értéke nem puszta szám. Magával viszi az eredetét - a jogi hivatkozásokat, a forráshivatkozásokat és az őt előállító képletazonosítót - a registry-definíciótól egészen a kezelő felé mutató kimenetig.
flowchart LR
DEF["Registry casilla definition — legal_refs · source_refs · formula_id"]
subgraph mesh["source-resolver mesh — merge_source_resolutions"]
direction TB
R1["Ledger aggregation resolvers"]
R2["Invoice catalogue resolver"]
R3["Previous-filing resolver"]
R4["Relation-prefill resolver"]
end
ENG["Registry formula engine — evaluates formula_id"]
OBS["CasillaObservation — value + legal_refs + source_refs + formula_id"]
REV["CalculationRevision.observations (+ flat casilla_values)"]
PAY["CLI payloads"]
OPS["Operator surface — JSON envelope + text"]
DEF --> ENG
DEF --> mesh
R1 --> ENG
R2 --> ENG
R3 --> ENG
R4 --> ENG
ENG --> OBS --> REV --> PAY --> OPS
Szöveges alternatíva. Egy registry casilla-definíció, valamint a feloldott ledger-, számla-, korábbi benyújtási és relációs bemenetek táplálják a képletmotort. Ez egy eredetet hordozó megfigyelést bocsát ki, amelyből számítási revízió, CLI-adatcsomag és kezelő felé mutató kimenet lesz.
Egy casilla minden bindingja típusos forrást deklarál. A feloldók hálója - ledger-aggregáció, számlakatalógus, korábbi benyújtás átvitele és modelók közötti relációs előtöltés - ezeket a forrásokat binding-értékekké alakítja, amelyeket a merge_source_resolutions fésül össze. A registry képletmotorja a casilla képletét a feloldott bemeneteken értékeli ki, és az eredményt egy CasillaObservation-ként bélyegzi le, amely magával viszi a legal_refs, source_refs és formula_id mezőit. Ez a megfigyelés a perzisztált CalculationRevision-ön belül halad, majd a CLI-adatcsomagokba, majd a kezelőhöz. Az eredet soha nem esik ki a kifelé vezető úton.
A kötés vetítési szerződés, nem csatolási hely. Az általa birtokolt forráscsaládot azonosítja, ellenőrzi a szelektort és az aggregációt, valamint megadja, hogyan lesz a forrásból bevallási bemenet. A skaláris szerződés egy értéket állít elő. Az ismétlődő rekordcsaládok soronként egy tipizált kötést deklarálnak. Az értékeket csoportosítással és az egytől induló sorszámmal kapcsolják össze. A számítási felülvizsgálat rögzíti a feloldott sor-kötéseket. Az érvényesített részletsorokat előállító útvonalak ezeket külön tárolják. Soha nem csatol átlátszatlan rekordblokkot casillához.
A Modelo 720 szemlélteti az ismétlődő szerkezetet: külföldi eszközöket feloldó komponense be van jegyezve a forrásmeshbe, és tipizált eszközmezőket vetít a nyilvántartás sorkötéseibe. A készletnyilvántartás más. A InventoryLedger megvalósított, titkosított üzleti aggregátum. A kötési forrástaxonómiában jelenleg nincs készlettípus és nincs bejegyzett készletfeloldó. Ezért a modell-számítási felülvizsgálatokon kívül marad mindaddig, amíg jogilag megalapozott vetítés nem készül.
A perzisztencia és a biztonsági határ¶
Minden érzékeny pénzügyi adat egy helyen él: egy titkosított, profilonkénti tárolóban. A szerkezet, nem egy megegyezés tartja ott.
flowchart TD
OP(["Operator"])
subgraph boundary["Encrypted bucket-scoped store — financial data never leaves (no temp / scratch / plaintext)"]
direction TB
PROF["Active profile — resolve_active_bucket_id"]
SESS["BucketSession — KEK/DEK · idle-timed · one taxpayer at a time"]
FAC["Runtime factories — secure_object_repository_for_active_bucket"]
REPO["SecureObjectRepository — AEAD payloads · HMAC-SHA256 lookup digests"]
MK["MasterKeyProvider — Keyring / FileFallback · AES-256"]
DB[("SQLite with encrypted payload columns")]
ATT["AttachmentStore — put_bytes / read_bytes · content-addressed"]
EV["Evidence bytes — invoices · statements (FINANCIAL)"]
PROF --> SESS --> FAC --> REPO
REPO --> MK
REPO --> DB
ATT --> REPO
EV --> ATT
end
SEDE["adapters/outbound/aeat — read-only live checks"]
AEAT["AEAT"]
HUM{{"Human filing — outside the app"}}
OP --> PROF
SEDE -.->|"read-only operator live checks"| AEAT
OP --> HUM
HUM -.->|"manual submission"| AEAT
Szöveges alternatíva. A kezelő kiválaszt egy aktív profilt. Az ebből származó bucket-munkamenet futásidejű gyárakat és egy biztonságos tárolót nyit meg, amely titkosítja az adatcsomagokat a helyi adatbázisban és a csatolt bizonyítékokban. A kezelő AEAT-ellenőrzései csak olvashatók maradnak; kizárólag az emberi benyújtási cselekvés nyújthat be az AEAT-hoz.
A kulcstitkosító kulcsok (KEK-ek) védik az adattitkosító kulcsokat (DEK-eket). A tároló hitelesített, társított adatot tartalmazó titkosítású (AEAD) adatcsomagokat, valamint mesterkulcsból származtatott anyagból kulcsolt HMAC-SHA256 kereső-lenyomatokat használ. A HMAC hash-alapú üzenethitelesítő kódot jelent. A rejtjelezés a 256 bites kulcsokat használó Advanced Encryption Standard (AES-256).
Egyszerre egy adózóval dolgozik. Egy profil kiválasztása megnyit egy bucket-munkamenetet, amely egy SecureObjectRepository-t az adott adózó titkosított tárolójára hatókörez. A tároló minden adatcsomagot az oszlophatáron titkosít a MasterKeyProvider egy kulcsával - az operációs rendszer kulcstárolójából, vagy egy jelmondatból származtatott tartalékkal. A rejtjelezett szöveget egy helyi SQLite-adatbázisban perzisztálja, titkosított adatcsomag-oszlopokkal. A bizonyítékbájtok - számlák, kivonatok és visszafejtett dokumentumok - a tartalomcímzett AttachmentStore-on haladnak át, amely magukat a bájtokat tárolja, soha nem egy hivatkozást.
Az evidenciabájtok (számlák, kivonatok és visszafejtett dokumentumok) a tartalom alapján címzett AttachmentStore tárhelyen haladnak át, amely magukat a bájtokat tárolja, soha nem hivatkozást.
Az elemzett üzleti rekordok nem válnak csatolmányokká pusztán azért, mert később alátámaszthatnak egy bevallást. A tranzakciók, a számlakatalógusok és a készletnyilvántartás titkosított tárolóban maradnak különálló, tipizált aggregátumok. A Modelo 720 ezzel szemben a hívótól tipizált külföldi-eszköz megfigyeléseket kap. Egy bejegyzett forrásfeloldó csak a nyilvántartás által kért mezőket vetíti egy számítási felülvizsgálatba. A jelenlegi Modelo 100 nyilvántartásban a készlethez kapcsolódó 0177, 0181 és 0182 casillák továbbra is kézi bemenetek. A készletdomén most a 2025-ös nyitó-záró változást a 0177 és 0182 között osztja fel, de ez a doménvetítés nem bizonyít működő készlet-Renta útvonalat, és az 0181-re még nem állítja, hogy minden beszerzést tartalmaz.
Ebben a tárolóban semmi sem lép kifelé a hatóság felé írásként. A csak olvasható élő ellenőrzések kizárólag olvasásra érik el a hatóságot. Az egyetlen útvonal, amely írásként éri el a hatóságot, az emberi feltöltés, amely az eszköz határán túl helyezkedik el. Egy szerkezeti teszt kikényszeríti bármely írási ige hiányát az AEAT sede-adapterében, így a biztonsági helyzet nem erodálódhat véletlenül.
Hogyan marad hű a dokumentáció a kódhoz¶
Az a fegyelem, amely a rétegeket irányítja, a dokumentációt is irányítja. A Cadrumo három angol nyelvű dokumentációs felületet tart közel ahhoz a kódhoz, amely a tényeiket szolgáltatja.
A dokumentáció szerzői a kódtár markdown-ját írják - ezt az útmutatót és a többit a docs/ alatt - a projekthez tájékozódó emberek számára. A technikai felülvizsgálók minden állítást ellenőriznek a kóddal szemben, mielőtt bekerülne. A forráskódba ágyazott docstringek szolgáltatják az API-referenciát, így a szerzők soha nem másolnak egy szignatúrát a szövegbe. A generátorok magából a kódból állítják elő a forráskód- és parancssori referenciák vázát.
Mivel a generátorok a forrásból származtatják az API- és parancssori referenciákat, ezek a felületek nem sodródhatnak el észrevétlenül. Egy szigorú build a figyelmeztetéseket hibaként kezeli, és meghiúsul egy törött kereszthivatkozásnál, egy hiányzó csonknál vagy egy olyan parancshivatkozásnál, amely már nem egyezik a parancsokkal.
Belépés a kódba¶
Használja ezt az áttekintést a tájékozódáshoz, majd merüljön el a részletekben:
A rétegfa - böngéssze a
src/cadrumo/core,src/cadrumo/domain,src/cadrumo/application,src/cadrumo/adapterséssrc/cadrumo/entrypointsmappákat, hogy lássa az egyes csoportok által megnevezett alcsomagokat.A parancssori referencia - CLI-referencia a pontos igékhez, kapcsolókhoz és kimenethez.
Az API-referencia - /api/cadrumo a modulszignatúrákhoz és a teljes alcsomaglistához.
A registry szerzői útmutatója - Dokumentáció írása és felülvizsgálata ahhoz, hogyan írja meg azt a TOML-t, amelyet a feldolgozási folyamat lefordít.
A feldolgozási folyamat magyarázata - Hogyan alakítja a Cadrumo a nyilvántartásait adófájllá ugyanahhoz az úthoz, az adózó számára elmesélve.
A szójegyzék - Szójegyzék bármely kifejezéshez (casilla, modelo, fichero-BOE vagy justificante), amelynek a meghatározását keresi.
A működésbe hozás - Gyorsindító: állítson elő egy modelo-fájlt a telepítéshez és egy első benyújtás előkészítéséhez.
Közreműködés - a projekt forráskódja és hibajegykövetője a GitHubon található.