{"id":33926024,"url":"https://github.com/yawn/manifest","last_synced_at":"2026-04-06T03:36:49.508Z","repository":{"id":324397043,"uuid":"1096325939","full_name":"yawn/manifest","owner":"yawn","description":"Message catalogs with compile-time guarantees","archived":false,"fork":false,"pushed_at":"2026-03-18T17:31:49.000Z","size":108,"stargazers_count":1,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-19T06:50:41.077Z","etag":null,"topics":["auditing","logging","security"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yawn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-14T09:05:51.000Z","updated_at":"2026-03-18T17:31:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yawn/manifest","commit_stats":null,"previous_names":["yawn/manifest"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/yawn/manifest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yawn%2Fmanifest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yawn%2Fmanifest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yawn%2Fmanifest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yawn%2Fmanifest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yawn","download_url":"https://codeload.github.com/yawn/manifest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yawn%2Fmanifest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31458838,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditing","logging","security"],"created_at":"2025-12-12T10:03:27.499Z","updated_at":"2026-04-06T03:36:49.502Z","avatar_url":"https://github.com/yawn.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Manifest\n\n[![CI](https://github.com/yawn/manifest/actions/workflows/rust.yml/badge.svg)](https://github.com/yawn/manifest/actions/workflows/rust.yml) [![Crates](https://img.shields.io/crates/v/manifest.svg)](https://crates.io/crates/manifest) [![Docs](https://docs.rs/manifest/badge.svg)](https://docs.rs/manifest)\n\nThis crate provides a mechanism to manage catalogues of messages with critical semantics. When used in a build script, this message catalog is\nused to generate constants that must be used (or are marked as deprecated).\n\nOptionally (gated behind the `objects` feature) static references to `Message` structs can be obtained as well. These structs expose additional\nmetadata about the message. They implement the `Display` trait to render an equivalent to the constant value and implement a `Message` trait\nto enable passing messages over crate boundaries.\n\nMessages catalogues are useful for stakeholder communication (such as business sponsors, auditors or security teams) to communicate the entire\nset of critical events or state changes within an application.\n\nA message catalogue is stored in a file named `Manifest.toml` in the root of the project. It looks like this:\n\n```toml\n[1]\nmessage = \"user login\"\ncomment = \"User successfully logged in\"\n\n[2]\nmessage = \"login failed\"\ncomment = \"Authentication failed\"\n\n[100]\nmessage = \"deprecated feature\"\ncomment = \"This feature is no longer supported\"\ndeprecated = \"Use feature XYZ instead\"\n\n[5]\nmessage = \"password reset\"\n```\n\n## Usage\n\nWrite a `Manifest.toml` and add `manifest` to the build dependencies:\n\n```toml\n[build-dependencies]\nmanifest = { version = \"0.3\", features = [\"build\"] }\n```\n\nWrite a `build.rs` build script that calls the `manifest` crate to generate constants:\n\n```rust,ignore\nfn main() {\n    manifest::build::generate();\n}\n```\n\nAdd `manifest` as dependency:\n\n```toml\n[dependencies]\nmanifest = { version = \"0.3\" }\n```\n\nInitialize the constant inclusion once and use it:\n\n```rust,ignore\nmanifest::include_manifest!();\n\nuse crate::TEST_CRATE_00001_USER_LOGIN;\n\nuse tracing::trace;\n\nfn main() {\n    trace!(TEST_CRATE_00001_USER_LOGIN);\n}\n```\n\nThis example (using the manifest from above) would fail to compile since messages `2` and `5` are never used.\n\nIf a tracing subscriber would capture the `trace!` from above, the log message would look like this: `user login (TEST_CRATE_00001)`.\n\n## Objects\n\nWhen the `objects` feature is enabled, a `Message` struct is generated alongside the constants:\n\n```toml\n[dependencies]\nmanifest = { version = \"0.3\", features = [\"objects\"] }\n```\n\n```rust,ignore\nmanifest::include_manifest!();\n\nlet msg = Message::lookup(TEST_CRATE_00001_USER_LOGIN);\nassert_eq!(msg.id, 1);\nassert_eq!(msg.message, \"user login\");\nassert_eq!(msg.comment, Some(\"User successfully logged in\"));\n```\n\nThe `Message` trait allows passing messages across crate boundaries without depending on the generated types:\n\n```rust,ignore\nfn handle\u003cT: manifest::Message\u003e(msg: T) {\n    println!(\"id: {}, message: {}\", msg.id(), msg.message());\n\n    if let Some(tags) = msg.tags() {\n        println!(\"tags: {:?}\", tags);\n    }\n\n    if let Some(attrs) = msg.attributes() {\n        println!(\"attributes: {:?}\", attrs);\n    }\n}\n```\n\n### Schema\n\nA `[schema]` preamble can be added to `Manifest.toml` to define custom attributes and tags on messages:\n\n```toml\n[schema]\ntags = [\"security\", \"billing\", \"audit\"]\n\n[schema.attributes]\nsponsor = \"string\"\n\n[1]\nmessage = \"user login\"\ncomment = \"User successfully logged in\"\nsponsor = \"security-team\"\ntags = [\"security\", \"audit\"]\n\n[2]\nmessage = \"login failed\"\ncomment = \"Authentication failed\"\n```\n\n#### Tags\n\nTags are a closed set of allowed values defined in `[schema]`. Each message can have zero or more tags. A `Tag` enum is generated with PascalCase variants:\n\n```rust,ignore\n#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]\npub enum Tag { Audit, Billing, Security }\n```\n\nTags on the `Message` struct are available as `\u0026'static [Tag]` for typed local use. Through the `Message` trait, they are exposed as `Option\u003c\u0026'static [\u0026'static str]\u003e` for cross-crate compatibility — returning `None` when the schema doesn't define tags, or `Some` with the (possibly empty) tag list.\n\n#### Custom attributes\n\nCustom attributes are declared in `[schema.attributes]` and appear as `Option\u003c\u0026'static str\u003e` fields on the generated `Message` struct. Unknown attribute keys or tag values cause a build error.\n\nThrough the `Message` trait, attributes are exposed as `Option\u003cHashMap\u003c\u0026'static str, \u0026'static str\u003e\u003e` — returning `None` when the schema doesn't define attributes, or `Some` with a map of the attributes set on the message. The built-in field names `message`, `comment`, `deprecated`, and `tags` are reserved and cannot be used as attribute names.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyawn%2Fmanifest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyawn%2Fmanifest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyawn%2Fmanifest/lists"}