Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [ ] I have signed the Contributor Assignment Agreement.
102 changes: 102 additions & 0 deletions .github/codeql/suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,108 @@
"path": "nodedb/src/control/server/resp/gateway_dispatch.rs",
"sink": "^\\s*(assert!\\(result\\.is_ok\\(\\), \"RESP KV dispatch must succeed: \\{result:\\?\\}\"\\);|\"dispatch must still succeed with metering disabled: \\{result:\\?\\}\")$",
"reason": "Test-only: assert messages inside #[cfg(test)] mod tests print a test dispatch result when it fails. The session id is generated for a test session on a one-node test cluster, never a real client's, and the message goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-crs/src/parse/helmert_params.rs",
"sink": "^\\s*(\"\\{h:\\?\\}\"|assert!\\(close\\(r\\.dtz_m_per_yr,\\ 0\\.002\\),\\ \"\\{r:\\?\\}\"\\);)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-crs/src/parse/proj_string.rs",
"sink": "^\\s*(hom\\.gamma_c_deg)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-crs/src/parse/projjson_writer.rs",
"sink": "^\\s*(assert!\\(json\\.contains\\(r\\#\"\"name\":\"a\\ \\\\\"quoted\\\\\"\\ name\"\"\\#\\),\\ \"\\{json\\}\"\\);|assert_eq!\\(back,\\ def,\\ \"\\{text\\}\\\\n\\{json\\}\"\\);|parse_projjson\\(srid,\\ \"rt\",\\ \\&json\\)\\.unwrap_or_else\\(\\|e\\|\\ panic!\\(\"\\{text\\}\\\\n\\{json\\}\\\\n\\{e\\}\"\\)\\);)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-crs/src/parse/wkt2_writer.rs",
"sink": "^\\s*(assert_eq!\\(back,\\ def,\\ \"\\{text\\}\\\\n\\{wkt\\}\"\\);|let\\ back\\ =\\ parse_wkt2\\(srid,\\ \"rt\",\\ \\&wkt\\)\\.unwrap_or_else\\(\\|e\\|\\ panic!\\(\"\\{text\\}\\\\n\\{wkt\\}\\\\n\\{e\\}\"\\)\\);)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-query/src/geo_functions/crs.rs",
"sink": "^\\s*(assert!\\(\\(coordinates\\[0\\]\\ \\-\\ UTM47_X\\)\\.abs\\(\\)\\ <\\ 1e\\-3,\\ \"\\{coordinates:\\?\\}\"\\);|assert!\\(\\(coordinates\\[1\\]\\ \\-\\ UTM47_Y\\)\\.abs\\(\\)\\ <\\ 1e\\-3,\\ \"\\{coordinates:\\?\\}\"\\);)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-raster/src/crs/srid.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"expected\\ an\\ ambiguous\\ user\\ CRS,\\ got\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: an assert or panic inside #[cfg(test)] mod tests prints a CRS definition or coordinates built from hard-coded fixtures. Coordinates are map positions in test data, never user data, and the output goes to test results, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/conflict_policy.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"expected\\ AlterCollection,\\ got\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/copy_from.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected:\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/copy_from_stdin.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected:\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/copy_options.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected:\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/copy_to.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected:\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/credential.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected:\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/custom_type.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/dispatch.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"expected\\ AddMaterializedSum,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ AlterCollection,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ CreateCollection,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ CreateSequence,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ CreateTable,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ CreateTrigger,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ DropIndex,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ GrantRole,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ MatchQuery,\\ got\\ \\{other:\\?\\}\"\\),|other\\ =>\\ panic!\\(\"expected\\ RestoreTenant,\\ got\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb-sql/src/ddl_ast/parse/synonym_group.rs",
"sink": "^\\s*(other\\ =>\\ panic!\\(\"unexpected\\ \\{other:\\?\\}\"\\),)\\s*$",
"reason": "Test-only: a panic inside #[cfg(test)] mod tests prints a parsed statement built from hard-coded SQL when the match fails. Credential secrets in it are SecretText, whose Debug prints <redacted>. The panic goes to test output, not a log."
},
{
"rule": "rust/cleartext-logging",
"path": "nodedb/src/control/server/shared/session/audit_context.rs",
"sink": "^\\s*(assert!\\(!ctx\\.sql_text\\.contains\\(\"pw\\-secret\"\\),\\ \"\\{\\}\",\\ ctx\\.sql_text\\);|assert!\\(!ctx\\.sql_text\\.contains\\(\"tok\\-secret\"\\),\\ \"\\{\\}\",\\ ctx\\.sql_text\\);)\\s*$",
"reason": "Test-only: an assert inside #[cfg(test)] mod tests prints redacted SQL text when a fixture secret was not redacted. The secret is a hard-coded test literal, and the output goes to test results, not a log."
},
{
"rule": "rust/hard-coded-cryptographic-value",
"path": "nodedb/src/control/security/keystore/wal_key.rs",
"sink": "^\\s*(let\\ expected\\ =\\ nodedb_wal::crypto::WalEncryptionKey::with_epoch\\(\\&\\[0x24u8;\\ 32\\],\\ \\[0u8;\\ 4\\]\\);)\\s*$",
"reason": "Test-only: inside #[cfg(test)] mod tests, a fixed key and epoch build the expected key for a round-trip check against a fixture key file. No production key or nonce comes from it."
}
]
}
18 changes: 14 additions & 4 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Eight jobs on a nightly toolchain — only worth running when a change can
# Ten jobs on a nightly toolchain — only worth running when a change can
# reach a decoder. The weekly cron runs unconditionally, so a too-narrow path
# filter costs coverage for a week, not forever.

Expand All @@ -7,11 +7,15 @@ name: ASan fuzz + 32-bit corpus/property
on:
pull_request:
branches: [main]
# The crates the seven targets reach.
# The crates the nine targets and the wasm32 check reach.
paths:
- fuzz/**
- nodedb-codec/**
- nodedb-raster/**
- nodedb-raster-load/**
- nodedb-srid/**
- nodedb-crs/**
- nodedb-spatial/**
- nodedb-columnar/**
- nodedb-strict/**
- nodedb-wal/**
Expand Down Expand Up @@ -52,6 +56,10 @@ jobs:
dictionary: fuzz/dictionaries/sql.dict
- name: geotiff_decoder
dictionary: fuzz/dictionaries/binary.dict
- name: crs_text
dictionary: fuzz/dictionaries/crs.dict
- name: spatial_geometry
dictionary: fuzz/dictionaries/geometry.dict
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# A pinned nightly keeps the build cache key stable across days. Move
Expand All @@ -66,7 +74,7 @@ jobs:
with:
workspaces: fuzz -> target
key: ${{ matrix.target.name }}
# All seven matrix jobs install the same pinned binary; build it once.
# All nine matrix jobs install the same pinned binary; build it once.
- name: Cache cargo-fuzz
id: cache-cargo-fuzz
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
Expand Down Expand Up @@ -110,4 +118,6 @@ jobs:
- name: Check decoders build for wasm32
run: |
cargo check --target wasm32-unknown-unknown \
-p nodedb-codec -p nodedb-columnar -p nodedb-strict
-p nodedb-codec -p nodedb-columnar -p nodedb-strict \
-p nodedb-raster -p nodedb-raster-load \
-p nodedb-srid -p nodedb-crs -p nodedb-spatial
5 changes: 5 additions & 0 deletions .github/workflows/static-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,8 @@ jobs:
run: |
python3 scripts/ci/check_advisory_ignores.py --self-test
python3 scripts/ci/check_advisory_ignores.py
- name: EPSG table gate
run: |
python3 -m venv "$RUNNER_TEMP/proj"
"$RUNNER_TEMP/proj/bin/pip" install --quiet pyproj==3.8.0
"$RUNNER_TEMP/proj/bin/python" -I scripts/gen_epsg.py --check
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ jobs:
run: |
python3 scripts/ci/check_advisory_ignores.py --self-test
python3 scripts/ci/check_advisory_ignores.py
- name: EPSG table gate
run: |
python3 -m venv "$RUNNER_TEMP/proj"
"$RUNNER_TEMP/proj/bin/pip" install --quiet pyproj==3.8.0
"$RUNNER_TEMP/proj/bin/python" -I scripts/gen_epsg.py --check
- name: Install cargo-deny
uses: taiki-e/install-action@065d6a08a14e61e89fb0a4c10eecdbdef39c7d8e # v2
with:
Expand Down
25 changes: 25 additions & 0 deletions CLA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# CONTRIBUTOR ASSIGNMENT AGREEMENT

**NodeDB**

Date: the date on which the Contributor signs through the CLA assistant.

**PARTIES.** (1) **the person who signs through the CLA assistant, identified by their GitHub account** (the **"Contributor"**); and (2) **BIZ IMPULSE SOLUTIONS SDN. BHD.** (Company Registration No. 202201016965 (1462662-D)) (the **"Company"**).

**1. Contributions.** The Contributor has contributed or will contribute code, documentation and other material to the repositories at github.com/NodeDB-Lab/nodedb and github.com/NodeDB-Lab/nodedb-studio under the GitHub account through which the Contributor signs, from the first contribution to the date above, and will contribute more. Those contributions, and every later contribution that the Contributor submits to a repository of the Company, are the **"Contributions"**.

**2. Assignment.** In consideration of RM1.00, which the Contributor acknowledges receiving, and of the Company's promises in clauses 3 and 4, the Contributor sells and assigns to the Company absolutely all copyright and other intellectual property rights in the Contributions, including the right to sue for any past infringement. The parties intend this to be a sale for that consideration and not a gift. The assignment of each Contribution takes effect when it is made. This document is in writing, as section 27(3) of the Copyright Act 1987 requires, and section 27(6) of that Act allows the assignment of future works.

**3. Licence back.** The Company grants the Contributor a perpetual, irrevocable, worldwide, royalty-free, non-exclusive licence to use, copy, modify and distribute the Contributions for any purpose. The Contributions stay available to the public under their published licence.

**4. Credit and moral rights.** The Company will keep the Contributor's name in the project's commit history and credits. For the purposes of section 25 of the Copyright Act 1987, the Contributor consents to the modification and adaptation of the Contributions.

**5. Confirmation.** The Contributor confirms that:

(a) the Contributions are the Contributor's own original work, or the Contributor has the right to assign them;

(b) no employer or other person owns or claims the Contributions, or that person has consented in writing to the assignment in clause 2 and has given the Company a copy of its consent; and

(c) the Contributor knows of no third party right that the Contributions infringe.

**6. General.** No other payment is due. The Company will pay the stamp duty on this document and the cost of preparing it, and will stamp it within thirty (30) days after it is signed. The Contributor is not obliged to contribute again. The Contributor will, at the Company's request and cost, sign the documents that the Company reasonably requires to perfect its title. This document is governed by the laws of Malaysia, and the courts of Malaysia have exclusive jurisdiction.
12 changes: 8 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ These planes communicate only through bounded lock-free bridges:

**Mixing planes is a correctness bug, not a style issue.** Spawning a Tokio task from Data Plane code, or calling io_uring from Control Plane code, will be rejected in review regardless of how small the change is.

Before writing any Data Plane or engine code, read `nodedb/CLAUDE.md` in full. It covers the plane rules, engine routing via `EngineRules`, serialization requirements, error handling conventions, and file size limits — all of which are enforced in review.
Before writing any Data Plane or engine code, follow these rules. Review enforces them: plane separation, engine routing through `EngineRules`, MessagePack for internal transport, typed errors, and the 500-line file limit.

---

Expand Down Expand Up @@ -106,7 +106,7 @@ cargo nextest run --all-features # tests
cargo deny check # dependency audit
```

Key rules (full list in `nodedb/CLAUDE.md`):
Key rules:

- No `.unwrap()` in library code — use `thiserror`, propagate errors
- No `Result<T, String>` — always typed error enums
Expand Down Expand Up @@ -231,10 +231,14 @@ NodeDB uses a mixed-license model for its runtime and library crates:

| Crates | License |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| `nodedb-types`, `nodedb-client`, `nodedb-query`, `nodedb-codec`, `nodedb-spatial`, `nodedb-graph`, `nodedb-vector`, `nodedb-vector-gpu`, `nodedb-fts`, `nodedb-strict`, `nodedb-columnar`, `nodedb-array`, `nodedb-sql`, `nodedb-physical`, `nodedb-wal`, `nodedb-mem`, `nodedb-crdt` | [Apache 2.0](LICENSE.APACHE-2.0) |
| `nodedb-types`, `nodedb-srid`, `nodedb-crs`, `nodedb-client`, `nodedb-query`, `nodedb-codec`, `nodedb-spatial`, `nodedb-graph`, `nodedb-vector`, `nodedb-vector-gpu`, `nodedb-fts`, `nodedb-strict`, `nodedb-columnar`, `nodedb-array`, `nodedb-raster`, `nodedb-raster-load`, `nodedb-sql`, `nodedb-physical`, `nodedb-wal`, `nodedb-mem`, `nodedb-crdt` | [Apache 2.0](LICENSE.APACHE-2.0) |
| `nodedb` (server), `nodedb-bridge`, `nodedb-raft`, `nodedb-cluster` | [BUSL-1.1](LICENSE) |

**What this means for contributors:** contributions to Apache-2.0 crates are under Apache 2.0; contributions to server crates are under BUSL-1.1. No CLA is required for either.
**What this means for contributors:** you sign the Contributor Assignment Agreement (the CLA) once, before your first pull request merges. It assigns the copyright in your contributions to Biz Impulse Solutions Sdn. Bhd. and gives you a licence back to use your own code for any purpose. The code stays public under the licence of its crate: Apache 2.0 for the library crates, BUSL-1.1 for the server crates.

## Contributor Assignment Agreement

Our CLA assistant comments on your first pull request with a link to sign. You sign once for all later pull requests. The agreement is [CLA.md](CLA.md) in this repository. If you write code for an employer, your employer must consent in the form the agreement provides.

**What this means for SDK/tool builders:** you can depend on the Apache-2.0 crates freely in your own open-source or commercial projects. The BUSL restriction only applies to the server crates — you are not affected unless you are redistributing the NodeDB server itself as a hosted service.

Expand Down
Loading
Loading