@neus/sdk 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -9,7 +9,8 @@
9
9
  "License" shall mean the terms and conditions for use, reproduction,
10
10
  and distribution as defined by Sections 1 through 9 of this document.
11
11
 
12
- "Licensor" shall mean the copyright owner or entity granting the License.
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
13
14
 
14
15
  "Legal Entity" shall mean the union of the acting entity and all
15
16
  other entities that control, are controlled by, or are under common
@@ -34,13 +35,15 @@
34
35
  "Work" shall mean the work of authorship, whether in Source or
35
36
  Object form, made available under the License, as indicated by a
36
37
  copyright notice that is included in or attached to the work
37
- (which shall not include communication that is conspicuously
38
- marked or otherwise designated in writing by the copyright owner
39
- as "Not a Contribution").
38
+ (an example is provided in the Appendix below).
40
39
 
41
- "Contributor" shall mean Licensor and any individual or Legal Entity
42
- on behalf of whom a Contribution has been received by Licensor and
43
- subsequently incorporated within the Work.
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
44
47
 
45
48
  "Contribution" shall mean any work of authorship, including
46
49
  the original version of the Work and any modifications or additions
@@ -50,16 +53,20 @@
50
53
  the copyright owner. For the purposes of this definition, "submitted"
51
54
  means any form of electronic, verbal, or written communication sent
52
55
  to the Licensor or its representatives, including but not limited to
53
- communication on electronic mailing lists, source code control
54
- systems, and issue tracking systems that are managed by, or on behalf
55
- of, the Licensor for the purpose of discussing and improving the Work,
56
- but excluding communication that is conspicuously marked or otherwise
57
- designated in writing by the copyright owner as "Not a Contribution".
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
58
65
 
59
66
  2. Grant of Copyright License. Subject to the terms and conditions of
60
67
  this License, each Contributor hereby grants to You a perpetual,
61
68
  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
62
- copyright license to use, reproduce, prepare Derivative Works of,
69
+ copyright license to reproduce, prepare Derivative Works of,
63
70
  publicly display, publicly perform, sublicense, and distribute the
64
71
  Work and such Derivative Works in Source or Object form.
65
72
 
@@ -113,11 +120,12 @@
113
120
  that such additional attribution notices cannot be construed
114
121
  as modifying the License.
115
122
 
116
- You may add Your own copyright notice or additional
117
- terms and conditions for use, reproduction, or distribution of Your
118
- derivative works, or for any such Derivative Works as a whole,
119
- provided Your use, reproduction, and distribution of the Work
120
- otherwise complies with the conditions stated in this License.
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
121
129
 
122
130
  5. Submission of Contributions. Unless You explicitly state otherwise,
123
131
  any Contribution intentionally submitted for inclusion in the Work
@@ -154,28 +162,16 @@
154
162
  other commercial damages or losses), even if such Contributor
155
163
  has been advised of the possibility of such damages.
156
164
 
157
- 9. Accepting Warranty or Support. When redistributing the Work or
158
- Derivative Works thereof, You may choose to offer, and charge a fee
159
- for, acceptance of support, warranty, indemnity, or other liability
160
- obligations and/or rights consistent with this License. However, in
161
- accepting such obligations, You may act only on Your own behalf and
162
- on Your sole responsibility, not on behalf of any other Contributor,
163
- and only if You agree to indemnify, defend, and hold each Contributor
164
- harmless for any liability incurred by, or claims asserted against,
165
- such Contributor by reason of your accepting any such warranty or support.
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
166
175
 
167
176
  END OF TERMS AND CONDITIONS
168
177
 
169
- Copyright 2025 NEUS Network, Inc.
170
-
171
- Licensed under the Apache License, Version 2.0 (the "License");
172
- you may not use this file except in compliance with the License.
173
- You may obtain a copy of the License at
174
-
175
- http://www.apache.org/licenses/LICENSE-2.0
176
-
177
- Unless required by applicable law or agreed to in writing, software
178
- distributed under the License is distributed on an "AS IS" BASIS,
179
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
180
- See the License for the specific language governing permissions and
181
- limitations under the License.
package/README.md CHANGED
@@ -1,206 +1,140 @@
1
1
  # NEUS SDK
2
2
 
3
- JavaScript client for NEUS Network. Handles wallet signing and API calls automatically.
3
+ JavaScript client (and optional widgets) for the NEUS Network verification API.
4
4
 
5
- ## Installation
5
+ ## Install
6
6
 
7
7
  ```bash
8
8
  npm install @neus/sdk
9
9
  ```
10
10
 
11
- ## Quick Start
11
+ ## Create a proof (browser wallet flow)
12
+
13
+ This path requests a wallet signature in the browser and submits the verification request:
12
14
 
13
15
  ```javascript
14
16
  import { NeusClient } from '@neus/sdk';
15
17
 
16
- const client = new NeusClient();
17
- const proof = await client.verify({
18
- verifier: 'ownership-basic',
19
- content: 'Hello NEUS Network'
20
- });
21
-
22
- console.log('Proof created:', proof.qHash);
23
- ```
24
-
25
- ## Basic Usage
26
-
27
- ### Create Proof
18
+ const client = new NeusClient({ apiUrl: 'https://api.neus.network' });
28
19
 
29
- ```javascript
30
- // Content ownership
31
- const proof = await client.verify({
20
+ const res = await client.verify({
32
21
  verifier: 'ownership-basic',
33
- content: 'My original content'
34
- });
35
-
36
- // NFT ownership
37
- const proof = await client.verify({
38
- verifier: 'nft-ownership',
39
- data: {
40
- ownerAddress: walletAddress,
41
- contractAddress: '0x...',
42
- tokenId: '1234',
43
- chainId: 1
44
- }
22
+ content: 'Hello NEUS',
23
+ wallet: window.ethereum
45
24
  });
46
25
 
47
- // Token holdings
48
- const proof = await client.verify({
49
- verifier: 'token-holding',
50
- data: {
51
- ownerAddress: walletAddress,
52
- contractAddress: '0x...',
53
- minBalance: '100.0',
54
- chainId: 1
55
- }
56
- });
26
+ // Proof ID (qHash): stable identifier you can store and use for status polling
27
+ const proofId = res.qHash;
28
+ const status = await client.getStatus(proofId);
57
29
  ```
58
30
 
59
- ### Check Status
31
+ ## Client configuration
60
32
 
61
33
  ```javascript
62
- // Public proof status
63
- const status = await client.getStatus(proof.qHash);
64
- console.log('Verified:', status.success);
65
-
66
- // Private proof access (requires wallet signature)
67
- const privateStatus = await client.getPrivateStatus(proof.qHash, wallet);
68
- ```
69
-
70
- ### Monitor Progress
71
-
72
- ```javascript
73
- // Poll until completion
74
- const finalStatus = await client.pollProofStatus(proof.qHash, {
75
- interval: 3000,
76
- onProgress: (status) => console.log('Current status:', status.status)
34
+ const client = new NeusClient({
35
+ // Optional: point at a self-hosted deployment
36
+ apiUrl: 'https://api.neus.network',
37
+ // Optional: request timeout (ms)
38
+ timeout: 30000,
39
+ // Optional: server-side enterprise API key for higher limits on eligible endpoints
40
+ // (Do not embed API keys in browser apps.)
41
+ apiKey: process.env.NEUS_API_KEY
77
42
  });
78
43
  ```
79
44
 
80
- ## Configuration
45
+ ## Create a proof (server / manual signing)
46
+
47
+ If you already have a signature over the NEUS Standard Signing String, submit it directly:
81
48
 
82
49
  ```javascript
83
- const client = new NeusClient({
84
- apiUrl: 'https://api.neus.network', // Default
85
- timeout: 30000 // Request timeout
50
+ const res = await client.verify({
51
+ verifierIds: ['ownership-basic'],
52
+ data: {
53
+ owner: '0x1111111111111111111111111111111111111111',
54
+ content: 'Hello NEUS',
55
+ reference: { type: 'url', id: 'https://example.com' }
56
+ },
57
+ walletAddress: '0x1111111111111111111111111111111111111111',
58
+ signature: '0x...',
59
+ signedTimestamp: Date.now(),
60
+ chainId: 84532,
61
+ options: { privacyLevel: 'private' }
86
62
  });
87
63
  ```
88
64
 
89
- ## Privacy Controls
65
+ ## What verifiers are available?
90
66
 
91
- ```javascript
92
- // Public proof - publicly accessible verification details
93
- const publicProof = await client.verify({
94
- verifier: 'ownership-basic',
95
- content: 'Public content',
96
- options: { privacyLevel: 'public' }
97
- });
67
+ Use the API directly (avoids drift):
98
68
 
99
- // Private proof - restricted access; details require wallet authentication
100
- const privateProof = await client.verify({
101
- verifier: 'ownership-basic',
102
- content: 'Private content',
103
- options: { privacyLevel: 'private' }
104
- });
105
- ```
69
+ - `GET /api/v1/verification/verifiers`
106
70
 
107
- ## Cross-Chain Storage
71
+ ## Gate checks (recommended for server-side gating)
108
72
 
109
- Store proofs on multiple testnets:
73
+ For production server-side gating, prefer the minimal public endpoint:
110
74
 
111
75
  ```javascript
112
- const proof = await client.verify({
113
- verifier: 'ownership-basic',
114
- content: 'Multi-chain proof',
115
- options: {
116
- targetChains: [11155111, 80002, 421614] // Testnet chains
117
- }
76
+ const res = await client.gateCheck({
77
+ address: '0x...',
78
+ verifierIds: ['token-holding'],
79
+ contractAddress: '0x...',
80
+ minBalance: '100',
81
+ chainId: 1,
82
+ // Optional: require a recent proof for point-in-time verifiers (example: last hour)
83
+ since: Date.now() - 60 * 60 * 1000
118
84
  });
119
- ```
120
-
121
- ## Error Handling
122
85
 
123
- ```javascript
124
- try {
125
- const proof = await client.verify({
126
- verifier: 'ownership-basic',
127
- content: 'Hello NEUS'
128
- });
129
- } catch (error) {
130
- if (error.code === 4001) {
131
- console.log('User cancelled verification');
132
- } else {
133
- console.error('Verification failed:', error.message);
134
- }
86
+ if (!res.data?.eligible) {
87
+ throw new Error('Access denied');
135
88
  }
136
89
  ```
137
90
 
138
- ## API Methods
139
-
140
- ### `verify(params)`
141
-
142
- Create verification proof.
143
-
144
- **Parameters:**
145
- - `verifier` (string) - Verifier ID
146
- - `content` (string) - Content to verify (for ownership-basic)
147
- - `data` (object) - Verifier-specific data
148
- - `options` (object) - Privacy and storage options
149
-
150
- **Returns:** `{ qHash, status, data }`
151
-
152
- ### `getStatus(qHash)`
91
+ Note: `gateCheck` evaluates **existing public/discoverable proofs**. For strict real-time decisions, create a new proof via `client.verify(...)` (or `POST /api/v1/verification`) and use the final status.
153
92
 
154
- Get proof status.
93
+ ## Lookup mode (Premium, server-side only; non-persistent)
155
94
 
156
- **Parameters:**
157
- - `qHash` (string) - Proof identifier
95
+ If you need a **real-time assessment** without minting/storing proofs (no `qHash`), use lookup mode:
158
96
 
159
- **Returns:** `{ success, status, data }`
97
+ - **Endpoint:** `POST /api/v1/verification/lookup`
98
+ - **Auth:** `Authorization: Bearer sk_live_...` (or `sk_test_...`)
99
+ - **Semantics:** runs `external_lookup` verifiers only; **does not** create a proof record
160
100
 
161
- ### `getPrivateStatus(qHash, wallet)`
101
+ Note: lookup mode is deployment-dependent and is not part of the stable public integrator OpenAPI (`docs/api/public-api.json`).
162
102
 
163
- Access private proof with wallet signature.
164
-
165
- **Parameters:**
166
- - `qHash` (string) - Proof identifier
167
- - `wallet` (object) - Wallet provider
168
-
169
- **Returns:** `{ success, status, data }`
170
-
171
- ### `pollProofStatus(qHash, options)`
172
-
173
- Poll until verification completes.
174
-
175
- **Parameters:**
176
- - `qHash` (string) - Proof identifier
177
- - `options` (object) - Polling configuration
178
- - `interval` (number) - Polling interval in ms
179
- - `timeout` (number) - Total timeout in ms
180
- - `onProgress` (function) - Progress callback
181
-
182
- **Returns:** `{ success, status, data }`
103
+ ```javascript
104
+ const res = await client.lookup({
105
+ // Premium API key (keep server-side only)
106
+ apiKey: process.env.NEUS_API_KEY,
107
+ verifierIds: ['wallet-risk'],
108
+ targetWalletAddress: '0x...',
109
+ data: { chainId: 1 }
110
+ });
183
111
 
184
- ### `isHealthy()`
112
+ if (!res.data?.verified) {
113
+ throw new Error('Rejected');
114
+ }
115
+ ```
185
116
 
186
- Check API connectivity.
117
+ Note: `gateCheck()` and `lookup()` are different tools.
118
+ - Use **`gateCheck()`** when you want to gate based on **existing public/discoverable proofs** (fast, minimal response).
119
+ - Use **`lookup()`** when you want a **fresh, non-persistent** decision (typically billable in hosted deployments).
120
+ - Only combine them if you are intentionally doing a cache-first strategy (gate-check first to avoid unnecessary lookups).
187
121
 
188
- **Returns:** `boolean`
122
+ ## Private proof reads (owner)
189
123
 
190
- ### `getVerifiers()`
124
+ - Private proof by Proof ID (qHash): `client.getPrivateStatus(qHash, wallet)`
125
+ - Private proofs by wallet/DID: `client.getPrivateProofsByWallet(walletOrDid, { limit, offset }, wallet)`
191
126
 
192
- List available verifiers.
127
+ ## React widgets
193
128
 
194
- **Returns:** `string[]`
129
+ For UI gating, see `./widgets/README.md`.
195
130
 
196
- ## Requirements
131
+ Widget imports:
197
132
 
198
- - **Node.js**: 18+
199
- - **Browser**: Modern browser with Web3 wallet
200
- - **Wallet**: MetaMask, WalletConnect, or ethers.js Wallet
133
+ ```javascript
134
+ import { VerifyGate, ProofBadge } from '@neus/sdk/widgets';
135
+ ```
201
136
 
202
- ## Links
137
+ ## Reference docs
203
138
 
204
- - **[Complete Reference](https://github.com/neus/network/tree/main/docs/REFERENCE.md)** - Full API and verifier documentation
205
- - **[Available Verifiers](https://github.com/neus/network/tree/main/docs/VERIFIERS.md)** - All verification types
206
- - **[GitHub Issues](https://github.com/neus/network/issues)** - Community support
139
+ - API Reference: `../docs/api/README.md`
140
+ - OpenAPI (JSON): `../docs/api/public-api.json`
package/SECURITY.md CHANGED
@@ -1,224 +1,29 @@
1
- # NEUS SDK Security Guidelines
2
-
3
- ## Overview
4
-
5
- The NEUS Network provides cryptographic verification infrastructure with strong security guarantees at the protocol level. Developers implementing custom verifiers or integrating the SDK must understand and follow security best practices to maintain system integrity.
6
-
7
- ## Core Security Model
8
-
9
- ### What NEUS Guarantees
10
-
11
- - **EIP-191/EIP-1271 Signature Verification**: All API calls require valid signatures (supports contract wallets)
12
- - **Replay Protection**: 5-minute timestamp windows with anti-replay protections
13
- - **Cross-Chain Integrity**: Cryptographic proofs propagated across multiple chains
14
- - **Immutable Audit Trail**: All verifications stored with quantum-safe qHash identifiers
15
- - **Privacy-Respecting IPFS**: Public snapshots protect sensitive data; signatures never exposed
16
-
17
- ### Developer Responsibilities
18
-
19
- - **Input Validation**: Sanitize all user-provided data before verification
20
- - **Contract Security**: Verify smart contract addresses before interaction
21
- - **API Rate Limiting**: Implement appropriate limits for external service calls
22
- - **Key Management**: Never expose private keys in verifier logic
23
-
24
- ## Verifier Security Checklist
25
-
26
- ### 1. Input Validation
27
-
28
- ```javascript
29
- // CORRECT: Validate inputs
30
- async verify(data, options) {
31
- // Validate address format
32
- if (!ethers.isAddress(data.contractAddress)) {
33
- throw new ValidationError('Invalid contract address');
34
- }
35
-
36
- // Sanitize content
37
- const sanitizedContent = data.content.trim().slice(0, 1000);
38
-
39
- // Verify required fields (owner for ownership-basic/licensed, ownerAddress for nft-ownership/token-holding)
40
- if ((!data.owner && !data.ownerAddress) || !data.reference) {
41
- throw new ValidationError('Missing required fields');
42
- }
43
- }
44
-
45
- // WRONG: Direct usage without validation
46
- async verify(data, options) {
47
- const result = await contract.balanceOf(data.address); // Unsafe!
48
- }
49
- ```
50
-
51
- ### 2. External API Security
52
-
53
- ```javascript
54
- // CORRECT: Rate limiting and error handling
55
- class ExternalVerifier {
56
- constructor() {
57
- this.rateLimiter = new Map();
58
- this.maxRequests = 100; // per hour
59
- }
60
-
61
- async callExternalAPI(userId) {
62
- // Check rate limits
63
- if (this.isRateLimited(userId)) {
64
- throw new Error('Rate limit exceeded');
65
- }
66
-
67
- try {
68
- const result = await fetch(url, { timeout: 5000 });
69
- return result;
70
- } catch (error) {
71
- // Don't expose internal errors
72
- throw new Error('External verification failed');
73
- }
74
- }
75
- }
76
- ```
77
-
78
- ### 3. Smart Contract Interaction
79
-
80
- ```javascript
81
- // CORRECT: Verify contract bytecode
82
- async verifyContract(address, expectedBytecode) {
83
- const provider = new ethers.JsonRpcProvider(RPC_URL);
84
- const code = await provider.getCode(address);
85
-
86
- if (code === '0x') {
87
- throw new Error('No contract at address');
88
- }
89
-
90
- // Optionally verify against known bytecode
91
- if (expectedBytecode && code !== expectedBytecode) {
92
- throw new Error('Contract bytecode mismatch');
93
- }
94
- }
95
- ```
96
-
97
- ## Common Attack Vectors
98
-
99
- ### 1. Proof Spoofing
100
-
101
- **Risk**: Malicious users attempting to forge verification results
102
-
103
- **Mitigation**:
104
- - Always verify ownership through on-chain data or cryptographic signatures
105
- - Never trust client-provided verification results
106
- - Use the protocol's signature verification for all critical operations
107
- - Use `verifierContentHash` for proof-of-existence; avoid publishing full content unless explicitly intended
108
-
109
- ### 2. Replay Attacks
110
-
111
- **Risk**: Reusing old signatures or proofs
112
-
113
- **Mitigation**:
114
- - Built-in: 5-minute timestamp validation and anti-replay protections
115
- - Additional: Include chain-specific data in verification
116
-
117
- ### 3. Unintended Data Exposure
118
-
119
- **Risk**: Accidentally exposing private content in public snapshots
120
-
121
- **Mitigation**:
122
- - Set `privacyLevel: 'private'` and avoid `publicDisplay`/`storeOriginalContent`
123
- - For anchoring without exposure, use `enableIpfs: true` with `publicDisplay: false`, `storeOriginalContent: false`
124
- - Ensure UI defaults use secure privacy settings
125
-
126
- ### 4. Contract Upgrades
127
-
128
- **Risk**: Verified contracts changing implementation
129
-
130
- **Mitigation**:
131
- - Store contract address AND block number in proof
132
- - Consider proxy pattern detection
133
- - Document upgrade implications for users
134
-
135
- ## Rate Limiting Guidelines
136
-
137
- ### External APIs
138
-
139
- | Service Type | Recommended Limit | Timeout |
140
- |-------------|------------------|---------|
141
- | Blockchain RPC | 100 req/sec | 10s |
142
- | Social APIs | 10 req/min | 5s |
143
- | DNS Lookups | 50 req/min | 3s |
144
- | IPFS Gateway | 30 req/min | 30s |
145
-
146
- ### Implementation Example
147
-
148
- ```javascript
149
- class RateLimiter {
150
- constructor(maxRequests, windowMs) {
151
- this.requests = new Map();
152
- this.maxRequests = maxRequests;
153
- this.windowMs = windowMs;
154
- }
155
-
156
- allow(identifier) {
157
- const now = Date.now();
158
- const requests = this.requests.get(identifier) || [];
159
-
160
- // Clean old requests
161
- const valid = requests.filter(t => now - t < this.windowMs);
162
-
163
- if (valid.length >= this.maxRequests) {
164
- return false;
165
- }
166
-
167
- valid.push(now);
168
- this.requests.set(identifier, valid);
169
- return true;
170
- }
171
- }
172
- ```
173
-
174
- ## Error Handling
175
-
176
- ### Security-First Error Messages
177
-
178
- ```javascript
179
- // CORRECT: Generic external errors
180
- catch (error) {
181
- logger.error('Verification failed', {
182
- error: error.message,
183
- userId: data.owner
184
- });
185
- throw new Error('Verification failed');
186
- }
187
-
188
- // WRONG: Exposing internal details
189
- catch (error) {
190
- throw new Error(`Database query failed: ${error.stack}`);
191
- }
192
- ```
193
-
194
- ## Reporting Security Issues
195
-
196
- Found a security vulnerability? Please report it responsibly:
197
-
198
- 1. **DO NOT** create public GitHub issues for security vulnerabilities
199
- 2. Email: dev@neus.network
200
- 3. Include:
201
- - Description of the vulnerability
202
- - Steps to reproduce
203
- - Potential impact
204
- - Suggested fix (if applicable)
205
-
206
- ## Security Updates
207
-
208
- Monitor security updates:
209
- - GitHub Security Advisories: https://github.com/neus/network/security
210
- - NPM Audit: Run `npm audit` regularly
211
- - Email updates: dev@neus.network
212
-
213
- ## Compliance
214
-
215
- The NEUS Network is designed for:
216
- - GDPR compliance (no PII storage by default)
217
- - Cryptographic proof integrity
218
- - Decentralized trust model
219
-
220
- However, verifier implementations must ensure their own compliance based on data handled.
221
-
222
- ---
223
-
224
- *Version: 1.0.0*
1
+ # NEUS SDK security notes
2
+
3
+ Treat **wallet signatures** and **API keys** as secrets. Do not log them, expose them to clients, or store them in analytics.
4
+
5
+ ## Authentication model (public surface)
6
+
7
+ - **Verification submission** (`POST /api/v1/verification`) is authenticated by a signature over the **NEUS Standard Signing String**.
8
+ - **Status by Proof ID (qHash)** (`GET /api/v1/verification/status/{qHash}`) is safe to call publicly.
9
+ - **Owner-only reads** of private proof payloads require an additional owner signature. The SDK uses:
10
+ - `x-wallet-address`
11
+ - `x-signature`
12
+ - `x-signed-timestamp`
13
+
14
+ ## Do not
15
+
16
+ - Do not treat proof signatures as bearer tokens (they are request-bound).
17
+ - Do not embed API keys in browser apps. Keep API keys server-side only.
18
+ - Do not log or persist:
19
+ - proof signatures
20
+ - API keys
21
+ - third-party auth credentials or provider tokens (if your integration uses them)
22
+
23
+ ## Recommended privacy defaults
24
+
25
+ - `privacyLevel: 'private'`
26
+ - `publicDisplay: false`
27
+ - `storeOriginalContent: false`
28
+
29
+ “Discoverable” proofs are **public** (`privacyLevel='public'`) and explicitly opted into discovery (`publicDisplay=true`).