diff --git a/Cargo.toml b/Cargo.toml index 00179f9..1fd1c4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 304 +# version: 305 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.13-pre.2" +version = "0.2.13-pre.3" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-interface-lib/src/error.rs b/crates/ksp-interface-lib/src/error.rs new file mode 100644 index 0000000..c76d16b --- /dev/null +++ b/crates/ksp-interface-lib/src/error.rs @@ -0,0 +1,6 @@ +// file: crates/ksp-interface-lib/src/error.rs +// version: 1 + +/// Error code used when a bounded passive Program instruction contract exceeds one of its Interface-owned admission limits. +pub const ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED: ksp_core_lib::ErrorCode = + ksp_core_lib::ErrorCode::new("interface", "program_instruction_limit_exceeded"); diff --git a/crates/ksp-interface-lib/src/lib.rs b/crates/ksp-interface-lib/src/lib.rs index 2d3072f..467b67c 100644 --- a/crates/ksp-interface-lib/src/lib.rs +++ b/crates/ksp-interface-lib/src/lib.rs @@ -1,5 +1,5 @@ // file: crates/ksp-interface-lib/src/lib.rs -// version: 1 +// version: 2 #![warn(missing_docs)] #![deny(unreachable_pub)] @@ -7,10 +7,19 @@ //! Passive wire contracts shared by KSP Program implementations. //! -//! The foundation deliberately starts with the canonical Solana [`Pubkey`] -//! owned by `ksp-core-lib`. Program-facing instruction contracts are added in -//! later slices without introducing runtime, transport, persistence or Program -//! behavior into Interface. +//! The foundation reuses the canonical Solana [`Pubkey`] owned by +//! `ksp-core-lib` and exposes only bounded, passive Program-facing structures. +//! Runtime, transport, persistence and Program behavior remain outside this +//! crate. +mod error; +mod program_account_meta; + +/// Error code used when an Interface-owned Program instruction admission limit is exceeded. +pub use self::error::ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED; +/// Maximum number of account metas admitted by one passive Program instruction contract. +pub use self::program_account_meta::MAX_PROGRAM_INSTRUCTION_ACCOUNTS; +/// Passive account metadata attached to one Program instruction. +pub use self::program_account_meta::ProgramAccountMeta; /// Canonical Solana account address primitive owned by `ksp-core-lib`. pub use ksp_core_lib::Pubkey; diff --git a/crates/ksp-interface-lib/src/program_account_meta.rs b/crates/ksp-interface-lib/src/program_account_meta.rs new file mode 100644 index 0000000..7abbede --- /dev/null +++ b/crates/ksp-interface-lib/src/program_account_meta.rs @@ -0,0 +1,52 @@ +// file: crates/ksp-interface-lib/src/program_account_meta.rs +// version: 1 + +/// Maximum number of account metas admitted by one passive Program instruction contract. +pub const MAX_PROGRAM_INSTRUCTION_ACCOUNTS: usize = 255; + +/// Passive account metadata attached to one Program instruction. +/// +/// Account metas preserve the caller-provided Solana account identity and the +/// signer/writable flags without applying Program-specific semantics. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ProgramAccountMeta { + pubkey: crate::Pubkey, + is_signer: bool, + is_writable: bool, +} + +impl ProgramAccountMeta { + /// Creates one read-only account meta. + #[must_use] + pub const fn readonly(pubkey: crate::Pubkey, is_signer: bool) -> Self { + return Self { pubkey, is_signer, is_writable: false }; + } + + /// Creates one writable account meta. + #[must_use] + pub const fn writable(pubkey: crate::Pubkey, is_signer: bool) -> Self { + return Self { pubkey, is_signer, is_writable: true }; + } + + /// Returns whether this account must sign the containing instruction. + #[must_use] + pub const fn is_signer(&self) -> bool { + return self.is_signer; + } + + /// Returns whether this account may be written by the containing instruction. + #[must_use] + pub const fn is_writable(&self) -> bool { + return self.is_writable; + } + + /// Returns the canonical account address. + #[must_use] + pub const fn pubkey(&self) -> &crate::Pubkey { + return &self.pubkey; + } +} + +#[cfg(test)] +#[path = "../unit_tests/program_account_meta.rs"] +mod tests; diff --git a/crates/ksp-interface-lib/tests/dependency_boundary.rs b/crates/ksp-interface-lib/tests/dependency_boundary.rs index 2d03807..031c3aa 100644 --- a/crates/ksp-interface-lib/tests/dependency_boundary.rs +++ b/crates/ksp-interface-lib/tests/dependency_boundary.rs @@ -1,7 +1,7 @@ // file: crates/ksp-interface-lib/tests/dependency_boundary.rs -// version: 1 +// version: 2 -//! Dependency and passive-surface canaries for the Interface scaffold. +//! Dependency and passive-surface canaries for the Interface foundation. #[test] fn pre_002_manifest_has_exact_core_only_runtime_dependency() { @@ -45,10 +45,11 @@ fn pre_002_manifest_has_exact_core_only_runtime_dependency() { } #[test] -fn pre_002_scaffold_remains_passive_without_runtime_logging_surface() { +fn pre_003_surface_remains_passive_without_instruction_or_runtime_logging() { let crate_root = include_str!("../src/lib.rs"); - assert!(crate_root.contains("pub use ksp_core_lib::Pubkey;")); - assert!(!crate_root.contains("ProgramAccountMeta")); + assert!(crate_root.contains("ProgramAccountMeta")); + assert!(crate_root.contains("MAX_PROGRAM_INSTRUCTION_ACCOUNTS")); + assert!(crate_root.contains("ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED")); assert!(!crate_root.contains("ProgramInstruction")); assert!(!crate_root.contains("TRACING_TARGET")); assert!(!crate_root.contains("ksp_logging_lib")); diff --git a/crates/ksp-interface-lib/tests/public_api.rs b/crates/ksp-interface-lib/tests/public_api.rs index f45111e..2633799 100644 --- a/crates/ksp-interface-lib/tests/public_api.rs +++ b/crates/ksp-interface-lib/tests/public_api.rs @@ -1,7 +1,7 @@ // file: crates/ksp-interface-lib/tests/public_api.rs -// version: 1 +// version: 2 -//! Integration canaries for the public `ksp-interface-lib` scaffold. +//! Integration canaries for the public `ksp-interface-lib` foundation. fn consume_pubkey(pubkey: ksp_interface_lib::Pubkey) -> [u8; 32] { return pubkey.to_bytes(); @@ -13,3 +13,26 @@ fn public_pre_002_pubkey_contract_is_available_from_crate_root() { assert_eq!(consume_pubkey(pubkey), [0_u8; 32]); return; } + +#[test] +fn public_pre_003_account_meta_and_limit_contracts_are_available_from_crate_root() { + let pubkey = ksp_interface_lib::Pubkey::new_from_array([3_u8; 32]); + let readonly = ksp_interface_lib::ProgramAccountMeta::readonly(pubkey, true); + let writable = ksp_interface_lib::ProgramAccountMeta::writable(pubkey, false); + assert_eq!(readonly.pubkey(), &pubkey); + assert!(readonly.is_signer()); + assert!(!readonly.is_writable()); + assert_eq!(writable.pubkey(), &pubkey); + assert!(!writable.is_signer()); + assert!(writable.is_writable()); + assert_eq!(ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS, 255); + return; +} + +#[test] +fn public_pre_003_interface_error_code_is_stable_and_core_owned() { + let code: ksp_core_lib::ErrorCode = ksp_interface_lib::ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED; + assert_eq!(code.domain(), "interface"); + assert_eq!(code.code(), "program_instruction_limit_exceeded"); + return; +} diff --git a/crates/ksp-interface-lib/unit_tests/program_account_meta.rs b/crates/ksp-interface-lib/unit_tests/program_account_meta.rs new file mode 100644 index 0000000..fc0d7c9 --- /dev/null +++ b/crates/ksp-interface-lib/unit_tests/program_account_meta.rs @@ -0,0 +1,31 @@ +// file: crates/ksp-interface-lib/unit_tests/program_account_meta.rs +// version: 1 + +#[test] +fn readonly_and_writable_constructors_preserve_identity_signer_and_writable_flags() { + let readonly_pubkey = crate::Pubkey::new_from_array([7_u8; 32]); + let writable_pubkey = crate::Pubkey::new_from_array([9_u8; 32]); + let readonly = crate::ProgramAccountMeta::readonly(readonly_pubkey, true); + assert_eq!(readonly.pubkey(), &readonly_pubkey); + assert!(readonly.is_signer()); + assert!(!readonly.is_writable()); + let writable = crate::ProgramAccountMeta::writable(writable_pubkey, false); + assert_eq!(writable.pubkey(), &writable_pubkey); + assert!(!writable.is_signer()); + assert!(writable.is_writable()); + return; +} + +#[test] +fn account_meta_accepts_opaque_pubkeys_without_program_registry_validation() { + let opaque_pubkey = crate::Pubkey::new_from_array([0xA5_u8; 32]); + let meta = crate::ProgramAccountMeta::readonly(opaque_pubkey, false); + assert_eq!(meta.pubkey(), &opaque_pubkey); + return; +} + +#[test] +fn account_limit_constant_matches_the_interface_admission_contract() { + assert_eq!(crate::MAX_PROGRAM_INSTRUCTION_ACCOUNTS, 255); + return; +} diff --git a/deltas/0.2.13/pre.003.md b/deltas/0.2.13/pre.003.md new file mode 100644 index 0000000..6fad76b --- /dev/null +++ b/deltas/0.2.13/pre.003.md @@ -0,0 +1,272 @@ + + + +# Delta `0.2.13-pre.003` — `ProgramAccountMeta` + borne accounts + +## 1. Base requise + +Cette tranche s'applique exclusivement sur : + +```text +v0.2.12 ++ 0.2.13-pre.001 ++ 0.2.13-pre.002 +``` + +Le gate opérateur fourni pour `pre.002` est intégralement vert : + +```text +cargo fmt --all PASS +python3 scripts/audit_rust_workspace_rules.py PASS +python3 scripts/audit_markdown_tables.py ... PASS +cargo check --workspace PASS +cargo clippy --workspace --all-targets PASS +cargo test -p ksp-interface-lib PASS +cargo test --workspace PASS +cargo tree -p ksp-interface-lib --edges normal inspecté +cargo tree --duplicates inspecté +``` + +Le graphe ciblé confirme : + +```text +ksp-interface-lib +└── ksp-core-lib + └── solana-pubkey 4.3.0 +``` + +Aucune dépendance codec/runtime n'est introduite par Interface et les doublons workspace observés sont préexistants à cette crate. + +La version workspace passe de : + +```text +0.2.13-pre.2 +``` + +à : + +```text +0.2.13-pre.3 +``` + +## 2. Objectif + +Matérialiser uniquement la primitive passive représentant un account meta d'instruction Program, figer la borne publique du nombre d'account metas et introduire le code d'erreur Interface minimal nécessaire à la future admission de `ProgramInstruction`. + +La tranche ajoute : + +```text +ProgramAccountMeta +MAX_PROGRAM_INSTRUCTION_ACCOUNTS = 255 +ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED +unit tests de la primitive +public API canaries correspondants +``` + +Elle n'ajoute pas encore : + +```text +ProgramInstruction +MAX_PROGRAM_INSTRUCTION_DATA_LEN +enforcement de collection 255/256 +data payload +Debug résumé d'instruction +serde / serde_json +borsh / bincode / wincode +solana-instruction +logging/runtime +Program behavior +``` + +## 3. `ProgramAccountMeta` + +La primitive possède trois champs privés : + +```text +Pubkey +is_signer +is_writable +``` + +Les constructeurs publics sont : + +```text +ProgramAccountMeta::readonly(pubkey, is_signer) +ProgramAccountMeta::writable(pubkey, is_signer) +``` + +Les accessors publics sont : + +```text +pubkey() +is_signer() +is_writable() +``` + +Le type reste strictement passif : + +- aucune validation de registry Program n'est appliquée au `Pubkey` ; +- aucune policy signer/writable n'est inventée ; +- aucune sérialisation ou conversion vers `solana-instruction::AccountMeta` n'est ajoutée ; +- les champs privés empêchent une dérive future de représentation sans passer par l'API possédée par Interface. + +## 4. Borne accounts + +La façade expose : + +```rust +pub const MAX_PROGRAM_INSTRUCTION_ACCOUNTS: usize = 255; +``` + +Cette constante fixe le plafond d'admission retenu par le plan `0.2.13`. + +`pre.003` ne crée volontairement aucune collection artificielle autour de `ProgramAccountMeta` uniquement pour tester `255/256`. L'enforcement concret sera réalisé dans `ProgramInstruction::try_new` à `pre.004`, lorsque la collection existera réellement. + +La borne data `10_240` reste également réservée à `pre.004` avec le payload qu'elle protège. + +## 5. Modèle d'erreur minimal + +Interface continue d'utiliser `ksp_core_lib::Error`, `ErrorCode` et `Result`; aucun second type d'erreur n'est introduit. + +La seule catégorie matérialisée est : + +```text +interface.program_instruction_limit_exceeded +``` + +via : + +```text +ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED +``` + +Le code `invalid_program_instruction` n'est pas ajouté : aucun invariant de forme distinct des bornes n'existe encore dans la foundation. Le créer uniquement par symétrie serait prématuré. + +À `pre.004`, les erreurs de borne devront limiter leur contexte aux longueurs et plafonds sûrs ; aucun payload ni compte arbitraire ne devra être copié dans les diagnostics. + +## 6. Logging + +La décision de `pre.002` reste inchangée. Interface est toujours une crate de contrats passifs et n'émet aucun événement/span runtime. + +Restent donc absents : + +```text +ksp-logging-lib +src/constants.rs +TRACING_TARGET +tracing direct +``` + +## 7. Tests + +Les unit tests de `ProgramAccountMeta` couvrent : + +```text +readonly -> identité/signature conservées, writable=false +writable -> identité/signature conservées, writable=true +Pubkey opaque/non registry accepté +MAX_PROGRAM_INSTRUCTION_ACCOUNTS == 255 +``` + +`tests/public_api.rs` prouve depuis le crate-root : + +```text +construction readonly/writable +accessors publics +borne accounts publique +code d'erreur stable et typé par ksp_core_lib::ErrorCode +``` + +`tests/dependency_boundary.rs` conserve le firewall `pre.002` et vérifie désormais que : + +```text +ProgramAccountMeta est présent +MAX_PROGRAM_INSTRUCTION_ACCOUNTS est présent +ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED est présent +ProgramInstruction reste absent +logging/runtime restent absents +``` + +## 8. Fichiers ajoutés + +```text +crates/ksp-interface-lib/src/error.rs +crates/ksp-interface-lib/src/program_account_meta.rs +crates/ksp-interface-lib/unit_tests/program_account_meta.rs +deltas/0.2.13/pre.003.md +``` + +## 9. Fichiers modifiés + +```text +Cargo.toml +crates/ksp-interface-lib/src/lib.rs +crates/ksp-interface-lib/tests/dependency_boundary.rs +crates/ksp-interface-lib/tests/public_api.rs +docs/plans/020-V0_2_13_INTERFACE_PLAN.md +docs/validation/016-V0_2_13_INTERFACE.md +``` + +## 10. Fichiers volontairement inchangés + +```text +README.md +ROADMAP.md +CHANGELOG.md +.env.example +crates/ksp-interface-lib/Cargo.toml +crates/ksp-interface-lib/README.md +crates/ksp-interface-lib/USAGE.md +docs/architecture/** +docs/rules/** +crates/ksp-core-lib/** +crates/ksp-logging-lib/** +crates/ksp-onchain-transport-lib/** +crates/ksp-offchain-transport-lib/** +crates/ksp-config-lib/** +crates/ksp-wallet-lib/** +crates/ksp-app-*/** +prompts/** +``` + +README/USAGE restent dans leur lane de réconciliation finale `pre.007`; aucune documentation durable hors plan/validation n'est rouverte pour cette petite tranche fonctionnelle. + +## 11. Validations de génération + +Les audits Python sont rejoués sur l'arbre matérialisé avant livraison. Le sandbox de génération ne fournit pas `cargo`, `rustc` ou `rustfmt`; aucun nouveau PASS Cargo n'est donc revendiqué localement. + +## 12. Gate opérateur attendu + +Après application : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.13 +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-interface-lib +cargo test --workspace +cargo tree -p ksp-interface-lib --edges normal +cargo tree --duplicates +``` + +Une correction découverte par ce gate reste un `0.2.13-pre.003-fix.NNN` et n'avance pas `pre.004`. + +## 13. Suite + +Après gate vert, `pre.004` pourra matérialiser uniquement : + +```text +ProgramInstruction { program_id, accounts, data } +MAX_PROGRAM_INSTRUCTION_DATA_LEN = 10_240 +try_new borné +accessors +Debug résumé sans payload +acceptation 0/255 accounts et 0/10_240 data +rejet 256 accounts et 10_241 data +ordre et doublons conservés +contextes d'erreur sûrs +``` + +Aucun serde/codec ou comportement Program ne doit être ajouté dans cette tranche suivante. diff --git a/docs/plans/020-V0_2_13_INTERFACE_PLAN.md b/docs/plans/020-V0_2_13_INTERFACE_PLAN.md index a040ef8..cb0be42 100644 --- a/docs/plans/020-V0_2_13_INTERFACE_PLAN.md +++ b/docs/plans/020-V0_2_13_INTERFACE_PLAN.md @@ -1,5 +1,5 @@ - + # Plan `0.2.13` — Interface / wire foundation @@ -383,15 +383,15 @@ Relire les règles/architectures, auditer Core/Transport, classer kbot3, auditer ### pre.002 — scaffold `ksp-interface-lib` + façade + firewall -**Statut : réalisé ; gate opérateur à confirmer.** +**Statut : réalisé ; gate opérateur intégralement PASS.** Créer la crate, l'ajouter au workspace, poser `lib.rs` avec exports explicites, lints, README/USAGE initiaux et canaris manifest/firewall. Dépendance normale unique : `ksp-core-lib`. ### pre.003 — `ProgramAccountMeta` + bornes communes -**Statut : prévu** +**Statut : réalisé ; gate opérateur à confirmer.** -Matérialiser la primitive de compte ordonné, les constantes de borne, le modèle d'erreur Interface minimal et les unit/public canaries associés. Ne pas avancer `ProgramInstruction` si la tranche dépasse le budget. +Matérialiser la primitive de compte ordonné, la borne accounts, le modèle d'erreur Interface minimal et les unit/public canaries associés. `ProgramInstruction` et la borne data restent réservés à `pre.004`. ### pre.004 — `ProgramInstruction` passif borné @@ -479,3 +479,27 @@ aucun ksp-logging-lib / constants.rs / TRACING_TARGET ``` `pre.003` peut commencer après application du delta et gate opérateur vert. Sa responsabilité reste limitée à `ProgramAccountMeta`, aux bornes communes et au modèle d'erreur Interface minimal ; `ProgramInstruction` reste réservé à `pre.004`. + +## 17. État préparé `pre.003` + +`pre.003` matérialise uniquement la primitive de compte et les contrats nécessaires à la future admission de `ProgramInstruction` : + +```text +ProgramAccountMeta présent +fields privés +constructeurs readonly / writable +accessors pubkey / is_signer / is_writable +Pubkey Core réutilisé +MAX_PROGRAM_INSTRUCTION_ACCOUNTS 255 +ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED interface.program_instruction_limit_exceeded +ProgramInstruction absent par contrat +MAX_PROGRAM_INSTRUCTION_DATA_LEN absent jusqu'à pre.004 +serde / borsh / bincode / wincode absents +ksp-logging-lib / constants.rs / TRACING_TARGET absents +``` + +La constante `255` ferme le contrat public de borne accounts mais son enforcement `255/256` appartient au constructeur de `ProgramInstruction` de `pre.004`; `ProgramAccountMeta` représente un seul compte et n'invente donc pas une collection artificielle uniquement pour tester cette limite. + +Une seule catégorie d'erreur Interface est introduite. `invalid_program_instruction` reste absent : aucun invariant de forme distinct des limites n'est encore matérialisé et le créer par symétrie serait prématuré. Les futures erreurs de borne doivent utiliser `ksp_core_lib::Error/Result` et ne projeter que des longueurs/plafonds sûrs. + +Le passage à `pre.004` reste conditionné au gate opérateur complet sur l'overlay `pre.003`. diff --git a/docs/validation/016-V0_2_13_INTERFACE.md b/docs/validation/016-V0_2_13_INTERFACE.md index df7a202..2773d3f 100644 --- a/docs/validation/016-V0_2_13_INTERFACE.md +++ b/docs/validation/016-V0_2_13_INTERFACE.md @@ -1,5 +1,5 @@ - + # Validation `0.2.13` — Interface / wire foundation @@ -83,19 +83,19 @@ aucun comportement Program ## 7. API publique cible -| Contrat | Attendu final `0.2.13` | Statut | -|----------------------|--------------------------------------------------------|------------------| -| crate | `ksp-interface-lib` membre workspace | PASS pre.002 | -| façade | exports explicites crate-root; aucun `pub mod` | PASS pre.002 | -| Pubkey | réexport/usage contrôlé de Core; pas de type parallèle | PASS pre.002 | -| `ProgramAccountMeta` | private fields + writable/readonly + accessors | TODO pre.003 | -| `ProgramInstruction` | private fields + `try_new` + accessors | TODO pre.004 | -| account bound | `<= 255` | TODO pre.003/004 | -| data bound | `<= 10_240` | TODO pre.004 | -| serde | absent | FIXÉ pre.001 | -| generic codec | absent | FIXÉ pre.001 | -| Debug instruction | résumé borné, pas payload complet | TODO pre.004 | -| Error/Result | Core commun + codes Interface sûrs | TODO pre.003 | +| Contrat | Attendu final `0.2.13` | Statut | +|----------------------|--------------------------------------------------------|--------------| +| crate | `ksp-interface-lib` membre workspace | PASS pre.002 | +| façade | exports explicites crate-root; aucun `pub mod` | PASS pre.002 | +| Pubkey | réexport/usage contrôlé de Core; pas de type parallèle | PASS pre.002 | +| `ProgramAccountMeta` | private fields + writable/readonly + accessors | PASS pre.003 | +| `ProgramInstruction` | private fields + `try_new` + accessors | TODO pre.004 | +| account bound | constante publique `<= 255`; enforcement constructeur | PASS/PENDING | +| data bound | `<= 10_240` | TODO pre.004 | +| serde | absent | FIXÉ pre.001 | +| generic codec | absent | FIXÉ pre.001 | +| Debug instruction | résumé borné, pas payload complet | TODO pre.004 | +| Error/Result | Core commun + code Interface sûr minimal | PASS pre.003 | ## 8. Robustness/adversarial @@ -140,15 +140,15 @@ Si une nouvelle dépendance externe apparaît après `pre.001`, la présente mat ## 10. Tests de release -| Famille | Attendu | Statut | -|--------------------------|------------------------------------------------|--------------| -| unit tests privés | constructeurs/bornes/order/debug/errors | TODO | -| `tests/public_api.rs` | consommation crate-root uniquement | PASS pre.002 | -| external consumer canary | surface utilisable hors modules privés | TODO | -| dependency boundary | firewall exact | PASS pre.002 | -| release completeness | inventaire exact, aucun domaine supplémentaire | TODO | -| round-trip codec | aucun tant qu'aucun codec | N/A | -| network smoke | aucun pour crate wire pure | N/A | +| Famille | Attendu | Statut | +|--------------------------|-------------------------------------------------|--------------| +| unit tests privés | account meta/borne puis instruction/adversarial | PARTIEL | +| `tests/public_api.rs` | consommation crate-root uniquement | PASS pre.003 | +| external consumer canary | surface utilisable hors modules privés | TODO | +| dependency boundary | firewall exact | PASS pre.002 | +| release completeness | inventaire exact, aucun domaine supplémentaire | TODO | +| round-trip codec | aucun tant qu'aucun codec | N/A | +| network smoke | aucun pour crate wire pure | N/A | ## 11. Gate technique final attendu @@ -213,3 +213,24 @@ dependency firewall canary présent Le logging reste volontairement absent : la foundation `0.2.13` est passive et n'émet aucun événement/span runtime. Si une future surface comportementale démontre un besoin réel de logging, `ksp-logging-lib`, `src/constants.rs` et `TRACING_TARGET` devront être introduits ensemble conformément à `DEP-LOG-004` et `DEP-LOG-010`. Le passage à `pre.003` reste conditionné au gate opérateur complet sur l'overlay `pre.002`. + +## 14. État préparé `pre.003` + +| Critère | Statut | +|-----------------------------------------------------|---------------------------------------------| +| `ProgramAccountMeta` crate-root | PASS structurel | +| champs privés | PASS | +| constructeurs `readonly` / `writable` | PASS | +| accessors identité/signer/writable | PASS | +| Pubkey opaque non registry | PASS unit | +| `MAX_PROGRAM_INSTRUCTION_ACCOUNTS == 255` | PASS unit + public API | +| enforcement collection `255/256` | PENDING `pre.004` avec `ProgramInstruction` | +| code `interface.program_instruction_limit_exceeded` | PASS public API | +| type d'erreur propre Interface | ABSENT, Core commun conservé | +| `ProgramInstruction` | ABSENT par contrat | +| data bound | PENDING `pre.004` | +| serde/codecs | ABSENTS | +| logging/runtime | ABSENTS | +| dépendance normale | `ksp-core-lib` uniquement | + +Le statut `PASS/PENDING` de la borne accounts signifie que la valeur publique est désormais figée à `255`, tandis que le rejet concret de `256` comptes sera testé lorsque la collection existera dans `ProgramInstruction`. Aucun faux wrapper de collection n'est créé dans `pre.003`.