{"id":13419202,"url":"https://github.com/pellegre/libcrafter","last_synced_at":"2026-06-27T22:00:36.237Z","repository":{"id":5256690,"uuid":"6434669","full_name":"pellegre/libcrafter","owner":"pellegre","description":"A Rust library for constructing, sending, capturing, and decoding network packets","archived":false,"fork":false,"pushed_at":"2026-06-22T00:07:46.000Z","size":9714,"stargazers_count":312,"open_issues_count":0,"forks_count":87,"subscribers_count":30,"default_branch":"master","last_synced_at":"2026-06-22T00:12:49.554Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"adoprog/Sitecore-Courier","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pellegre.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2012-10-29T02:24:14.000Z","updated_at":"2026-06-22T00:07:48.000Z","dependencies_parsed_at":"2024-01-03T04:12:57.319Z","dependency_job_id":"7aeb86ca-7e57-49f1-88a0-43a82d0b6f58","html_url":"https://github.com/pellegre/libcrafter","commit_stats":{"total_commits":258,"total_committers":15,"mean_commits":17.2,"dds":0.4031007751937985,"last_synced_commit":"ce54715071493568005fa5f973042a0d147eb5c0"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/pellegre/libcrafter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pellegre%2Flibcrafter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pellegre%2Flibcrafter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pellegre%2Flibcrafter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pellegre%2Flibcrafter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pellegre","download_url":"https://codeload.github.com/pellegre/libcrafter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pellegre%2Flibcrafter/sbom","scorecard":{"id":726860,"data":{"date":"2025-08-11","repo":{"name":"github.com/pellegre/libcrafter","commit":"821a933cfcfc8dc0337d8bd3a6db3a5e2f063258"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 2/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T13:04:45.187Z","repository_id":5256690,"created_at":"2025-08-22T13:04:45.187Z","updated_at":"2025-08-22T13:04:45.187Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34869004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"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":[],"created_at":"2024-07-30T22:01:12.711Z","updated_at":"2026-06-27T22:00:36.232Z","avatar_url":"https://github.com/pellegre.png","language":"Rust","funding_links":[],"categories":["TODO scan for Android support in followings","Automation","\u003ca id=\"7bf0f5839fb2827fdc1b93ae6ac7f53d\"\u003e\u003c/a\u003e工具","自动化工具","Automation and Convention"],"sub_categories":["Code libraries and bindings","\u003ca id=\"32739127f0c38d61b14448c66a797098\"\u003e\u003c/a\u003e嗅探\u0026\u0026Sniff","代码库和绑定"],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/pellegre/libcrafter/HEAD/docs/assets/libcrafter-lockup-dark.svg\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pellegre/libcrafter/HEAD/docs/assets/libcrafter-lockup.svg\" alt=\"libcrafter\" width=\"560\"\u003e\n  \u003c/picture\u003e\n\u003c/h1\u003e\n\n`libcrafter` is a Rust workspace for packet-level network interaction. Its\npublic crate, `crafter`, lets agents and Rust tools build protocol-correct\npackets, place them on real networks, decode what comes back, and act on what\nthey observe.\n\nThis README is a progressive walkthrough: build your first packet, inspect and\ndecode bytes, read and write pcap, plan a send, and reach for disposable\nendpoints and labs when traffic cannot live on the developer machine. Every\nsnippet uses documentation address space (`192.0.2.0/24`, `198.51.100.0/24`,\n`2001:db8::/32`) and offline or dry-run defaults; live traffic is always an\nexplicit opt-in.\n\n## Your first packet\n\nA `Packet` is a typed stack of layers. Build one with `/` composition, then\n`compile()` to fill the dependent fields (lengths, protocol numbers, header\nlengths, checksums) that you did not set yourself:\n\n```rust\nuse crafter::prelude::*;\nuse std::net::Ipv4Addr;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let packet = Ipv4::new()\n        .src(Ipv4Addr::new(192, 0, 2, 10))\n        .dst(Ipv4Addr::new(198, 51, 100, 20))\n        / Icmpv4::echo_request().id(0x4242).seq(1)\n        / Raw::from(\"hello\");\n\n    let compiled = packet.compile()?;\n\n    println!(\"{}\", packet.summary());      // one-line stack summary\n    println!(\"{}\", packet.show());         // full field-by-field view\n    println!(\"{}\", compiled.hexdump());    // the bytes on the wire\n    Ok(())\n}\n```\n\n`compile()` fills only what you left unset. Anything you set explicitly survives\nuntouched — including values that are wrong on purpose — so the same builder\nemits both protocol-correct packets and deliberately malformed ones.\n\n## Inspect and decode\n\nReach into a packet by layer type, and decode raw bytes from an explicit link\nor network context. Decoding never guesses the entry point: you name the link\ntype or network layer.\n\n```rust\nuse crafter::prelude::*;\n\nfn inspect(frame: \u0026[u8], datagram: \u0026[u8]) -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // From an Ethernet frame:\n    let packet = Packet::decode_from_link(LinkType::Ethernet, frame)?;\n    if let Some(ip) = packet.layer::\u003cIpv4\u003e() {\n        println!(\"{} -\u003e {}\", ip.source(), ip.destination());\n    }\n\n    // From a bare IPv4 datagram:\n    let l3 = Packet::decode_from_l3(NetworkLayer::Ipv4, datagram)?;\n    println!(\"{}\", l3.summary());\n    Ok(())\n}\n```\n\nA malformed enclosing header surfaces as a structured error with `context`,\n`required`, and `available` rather than a panic, and any next protocol the\ndecoder does not model is preserved as a `Raw` payload when the header around it\nis valid. See [docs/reference/api.md](docs/reference/api.md) for the full decode\ncontract and typed-layer accessors.\n\n## Capture and pcap\n\nRead classic pcap files through the packet-wire API, apply a libpcap BPF\nfilter string, and iterate records with a `Sniffer`:\n\n```rust\nuse crafter::prelude::*;\n\nfn read_pcap(path: \u0026str) -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let source = PacketWire::pcap_file(path)\n        .filter(\"tcp or udp\")   // libpcap BPF filter string\n        .open()?\n        .source()?;\n\n    for record in Sniffer::new(source).collect_records()? {\n        println!(\"{}\", record.packet().summary());\n        println!(\"link type: {:?}\", record.metadata().link_type());\n    }\n    Ok(())\n}\n```\n\nWriting pcap is just as direct: compile packets, hand them to a pcap writer\nthrough `PacketWire`, and replay them later. The packet-wire layer covers\nclassic pcap read/write, libpcap BPF filters, offline sniffing, and bounded live\ncapture hooks. Full pcapng and a full BPF parser are not currently in scope. See\n[docs/reference/wire.md](docs/reference/wire.md) for sources, writers,\ntransmitters, and transform chains.\n\n## Send and receive\n\nSending is offline by default. `SendRecv` plans a send/receive without touching\nthe wire; `.dry_run()` is the default-safe mode, so no packet leaves the host.\nThe report still carries the attempts, the auto-derived reply filter, and any\nmatched reply:\n\n```rust\nuse crafter::prelude::*;\nuse std::net::Ipv4Addr;\nuse std::time::Duration;\n\nfn plan() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let packet = Ipv4::new()\n        .src(Ipv4Addr::new(192, 0, 2, 10))\n        .dst(Ipv4Addr::new(198, 51, 100, 20))\n        / Icmpv4::echo_request().id(0x4242).seq(1)\n        / Raw::from(\"ping\");\n\n    // SendRecv derives the BPF reply filter from the packet automatically.\n    let report = packet.send_recv_report(\n        SendRecv::new()\n            .iface(\"eth0\")\n            .network_layer()\n            .dry_run()                     // offline default: no packet leaves\n            .timeout(Duration::from_millis(250))\n            .retries(1),\n    )?;\n\n    println!(\"attempts: {}\", report.attempts());\n    println!(\"reply filter: {}\", report.effective_filter().unwrap_or(\"\"));\n    match report.reply() {\n        Some(reply) =\u003e println!(\"reply: {}\", reply.summary()),\n        None =\u003e println!(\"reply: none\"),\n    }\n    Ok(())\n}\n```\n\nThe live path is the same call with one explicit change — swap `.dry_run()` for\n`.live()`:\n\n```rust\nuse crafter::prelude::*;\n\nfn live(packet: \u0026Packet) -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let report = packet.send_recv_report(\n        SendRecv::new()\n            .iface(\"eth0\")\n            .network_layer()\n            .live(),                       // explicit opt-in: real raw send\n    )?;\n\n    if let Some(reply) = report.reply() {\n        println!(\"{}\", reply.summary());\n    }\n    Ok(())\n}\n```\n\nLive raw sends and captures require platform privileges, and you must be\nauthorized to send and capture on the target network. Keep live work off the\ndeveloper host — provision a disposable endpoint instead.\n\n## Tools: endpoint, lab, oracle, probe\n\nThe live path does not have to originate from your machine. Four modules under\n`tools/` provision disposable network positions, run packet work from them,\ncollect artifacts, and tear the resources down when the run is done:\n\n- **endpoint** — one disposable endpoint: doctor, create, exec, upload,\n  download, collect artifacts, destroy.\n- **lab** — multi-endpoint lab sessions that coordinate several endpoints for\n  one run.\n- **oracle** — packet-equivalence validation against reference backends\n  (offline, pcap, and live modes).\n- **probe** — peer-behavior validation against a live peer using seeded\n  profiles.\n\nThe stack layers as endpoint ← lab ← oracle/probe. Every invocation is offline\nby default; live traffic is an explicit opt-in. Start every provider-backed run\nwith `--dry-run`:\n\n```sh\ntools/endpoint/run doctor --provider hetzner --exposure wan --dry-run\ntools/lab/run doctor --provider hetzner --dry-run\ntools/oracle/run live --provider hetzner --dry-run --profile smoke --seed 1 --count 10\ntools/probe/run --provider hetzner --dry-run --profile smoke --seed 1 --count 10\n```\n\nOpt into live traffic only when an authorized human or agent has said so. The\nHetzner provider reads `HETZNER_API_TOKEN` or `HCLOUD_TOKEN` from the\nenvironment; never commit credentials, public IPs, or captures from sensitive\nnetworks.\n\n- [docs/operations/tools.md](docs/operations/tools.md) — the four-tool stack,\n  when to use which, and safe dry-run examples (start here).\n- [docs/operations/endpoint.md](docs/operations/endpoint.md) — disposable\n  endpoint setup, credentials, artifacts, and cleanup.\n- [docs/operations/lab.md](docs/operations/lab.md) — provider-backed\n  multi-endpoint lab sessions for oracle and probe workflows.\n\n## Protocol coverage\n\nEvery layer below is exported from `crafter::prelude` and slots into the same\nbuilder, decode, and summary surface. Unknown or unsupported next protocols are\npreserved as `Raw` payloads when the enclosing header is valid.\n\n| Layer | Coverage | Guide |\n| --- | --- | --- |\n| Ethernet / VLAN | Ethernet II and 802.1Q VLAN, Linux cooked capture, null/loopback | — |\n| IEEE 802.11 | Management, control, and data frames with radiotap and LLC/SNAP, EAPOL and RSN (802.11i) key-exchange fields; monitor-mode radiotap injection (transmit on the air) supported behind explicit live gates | [dot11](docs/guide/dot11.md) |\n| ARP | Request/reply construction and decode | [arp](docs/guide/arp.md) |\n| IPv4 | DSCP/ECN, protocol labels, checksum status, typed options, fragment fields (no automatic reassembly) | [ipv4](docs/guide/ipv4.md) |\n| IGMP | IPv4 packet-layer membership queries/reports, IGMPv1/v2 compatibility, IGMPv3 query/report records, generic extensions, and multicast router discovery packet shapes; not a router, snooper, proxy, or scanner | [igmp](docs/guide/igmp.md) |\n| IPv6 | Base header plus hop-by-hop, destination, fragment, routing, mobile-routing, and segment-routing extension headers | [ipv6](docs/guide/ipv6.md) |\n| ICMPv4 / ICMPv6 | ICMPv4 (with `Icmp` deprecated alias) and ICMP extensions (RFC 4884); ICMPv6 echo/errors, Neighbor Discovery (RFC 4861), MLD v1/v2, Extended Echo, experimental Node Information | [icmpv6](docs/guide/icmpv6.md) |\n| TCP | Segment construction, typed options, checksums | [tcp](docs/guide/tcp.md) |\n| UDP | UDP with options (RFC 9868) and checksum status | [udp](docs/guide/udp.md) |\n| QUIC | UDP-carried QUIC datagrams, long/short headers, Version Negotiation, Retry, Initial/Handshake/0-RTT packets, frames, transport parameters, protected-payload preservation, and probe dry-run/lab planning; not a QUIC endpoint stack | [quic](docs/guide/quic.md) |\n| DNS | EDNS(0), SVCB/HTTPS, DNSSEC record types | [dns](docs/guide/dns.md) |\n| DHCPv4 | BOOTP/DHCPv4 packet construction and decode, option overload, RFC 3396 long options, relay agent option 82, client identifiers, authentication, and leasequery packet fields; not a client, server, or lease engine | [dhcpv4](docs/guide/dhcpv4.md) |\n| DHCPv6 | DHCPv6 client/server and relay packet construction and decode, DUIDs, status codes, IA_NA, IA_PD, IA Address, IA Prefix, relay message encapsulation, leasequery families, and unknown option preservation; not a client, server, relay daemon, or lease engine | [dhcpv6](docs/guide/dhcpv6.md) |\n| BGP | OPEN, UPDATE, KEEPALIVE, NOTIFICATION, ROUTE-REFRESH, path attributes, capabilities | [bgp](docs/guide/bgp.md) |\n| MQTT | MQTT 3.1.1 and 5.0 control packets over TCP/1883, typed properties, reason codes, and stacked payload decode | [mqtt](docs/guide/mqtt.md) |\n| SNMP | BER values, VarBinds, SNMPv1/v2c PDUs, SNMPv3 wire framing, UDP/161 and UDP/162 decode dispatch, unknown preservation, and offline pcap fixtures; not a scanner, manager, agent daemon, MIB engine, credential store, or VACM evaluator | [snmp](docs/guide/snmp.md) |\n| OSPF | OSPFv2 Hello/DD/LSR/LSU/LSAck packets, Router/Network/Summary/AS-External/NSSA/Opaque (TE, RI) LSAs, null/simple/keyed-MD5/HMAC-SHA authentication, plus an OSPFv3 base layer; wire-level build and decode only (no state machine, SPF, or LSDB) | [ospf](docs/guide/ospf.md) |\n| IPsec | ESP, AH, and IKEv2 (IKE header and payload set) with SA and transform primitives | [ipsec](docs/guide/ipsec.md) |\n\nIP fragmentation and reassembly are explicit `IpFragment` / `IpDefrag` wire\ntransforms, not automatic decode-time behavior. TCP stream reassembly, full\npcapng, full BPF parsing, and a complete TCP/IP stack are not currently in\nscope.\n\n## Examples\n\nRust examples live under `crafter/examples/` and build against the public\n`crafter` crate. They are offline or dry-run unless an example is explicitly\nlive-gated:\n\n```sh\ncargo build -p crafter --examples\ncargo run -p crafter --example hello_world          # build, compile, hexdump\ncargo run -p crafter --example decode_bytes         # decode entry points\ncargo run -p crafter --example pcap_read            # pcap + Sniffer\ncargo run -p crafter --example send_recv_icmp       # dry-run send/receive\ncargo run -p crafter --example dns_query -- --name example.com\n```\n\nBy category:\n\n- Core packet model — `hello_world`, `packet_building`, `packet_inspection`,\n  `decode_bytes`, `custom_registry`.\n- Net workflows — `send_plan`, `send_packet`, `send_recv_icmp`, `network_ping`,\n  `batch_send`, `batch_send_recv`, `interface_helpers`, `ip_ranges`.\n- Pcap and sniffing — `pcap_write`, `pcap_read`, `wire_pcap_sniffer`,\n  `wire_transform_chain`, `ip_defrag_offline`, `ip_fragment_offline`,\n  `wpa_decrypt_offline`.\n- Protocols — `arp_who_has`, `dns_query`, `dhcpv4_discover`,\n  `dhcpv4_option82`, `dhcpv4_leasequery`, `dhcpv6_solicit`,\n  `dhcpv6_information_request`, `dhcpv6_prefix_delegation`, `dhcpv6_relay`,\n  `icmpv4_error`, `icmpv6_echo`, `snmp_get`, `snmp_trap`, `snmpv3_message`,\n  `vlan`, `dot11_beacon_rsn`, `ipsec_esp`, `bgp_session`, `mqtt_session`. SNMP wire\n  guidance also lives in\n  [docs/guide/snmp.md](docs/guide/snmp.md), and examples stay offline or\n  dry-run by default.\n\nThe full annotated table, with safety modes and commands, is in\n[docs/reference/examples.md](docs/reference/examples.md).\n\n## Documentation\n\n- [docs/README.md](docs/README.md) is the documentation index.\n- [docs/guide/](docs/guide/) — per-protocol wire coverage for everyday packet\n  work (IPv4, IGMP, IPv6, TCP, UDP, ARP, ICMPv6, DHCPv6, DNS, BGP, MQTT, SNMP,\n  OSPF, 802.11, IPsec); UDP, ARP, ICMPv6, IGMP, DHCPv6, SNMP, and OSPF now\n  have their own guides.\n- [docs/reference/](docs/reference/) — the public API\n  ([api.md](docs/reference/api.md)), the wire I/O layer\n  ([wire.md](docs/reference/wire.md)), and the example catalog\n  ([examples.md](docs/reference/examples.md)).\n- [docs/operations/](docs/operations/) — live, provider-backed, and manual\n  testing workflows (validation, probes, lab sessions, endpoints).\n- [docs/operations/tools.md](docs/operations/tools.md) — tools overview tying\n  the endpoint, lab, oracle, and probe modules together.\n- [CHANGELOG.md](CHANGELOG.md) records release scope and boundaries.\n\n## Validation\n\nLocal validation does not require provider credentials:\n\n```sh\ncargo test --workspace\ncargo doc --workspace --no-deps\n```\n\nThe full local release gate is:\n\n```sh\n.agents/scripts/check-crafter-release --static\n```\n\nProvider-backed validation starts with dry-runs against the oracle, probe, and\nendpoint runners before any live invocation. Oracle modes, backends, and CI\nexpectations are documented in\n[docs/operations/validation.md](docs/operations/validation.md).\n\n## Publishing\n\nThe final maintainer release checklist, including crates.io guardrails, is in\n[docs/operations/release.md](docs/operations/release.md).\n\nRun package-content checks before preparing a release:\n\n```sh\n.agents/scripts/check-crafter-release --package-only\n```\n\nRun the full local release gate before declaring the branch ready:\n\n```sh\n.agents/scripts/check-crafter-release --static\n```\n\nPrepare and validate a candidate version with the guarded release helper:\n\n```sh\n.agents/scripts/prepare-crafter-release --validate VERSION\n```\n\nFor agent-assisted publishing, use the repo-local `agent-cargo-publish` skill.\nIt runs the release gate, performs the guarded `cargo publish -p crafter\n--dry-run --locked`, summarizes the crate/version/commit and package contents,\nand requires explicit ask-tool approval before the real upload.\n\nThe maintainer publish entrypoint is:\n\n```sh\n.agents/scripts/publish-crafter-release VERSION\n```\n\nPublishing to crates.io is a final maintainer action. The publish script and\nskill enforce confirmation; do not run a real publish from unattended\nautomation.\n\n## License\n\nThis project is licensed under the MIT License. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpellegre%2Flibcrafter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpellegre%2Flibcrafter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpellegre%2Flibcrafter/lists"}