# kolaboro 0.1.0

Official clients for the [Kolaboro open data API](https://kolaboro.com/api/open): anonymous due-diligence data on off-plan
property projects (public checks, confirmations, tested developer claims, delays) plus the public log that proves what was
published and when. Data licence CC BY 4.0, credit Kolaboro. Code licence MIT.

Both clients check the Ed25519 signature of every answer before you get the data (header `x-kolaboro-signature`, key id in
`x-kolaboro-key-id`, keys at https://kolaboro.com/.well-known/kolaboro-keys.json). A missing or wrong signature raises
`KolaboroSignatureError`. The checks are the same code as https://kolaboro.com/open/kolaboro-verify.js and
https://kolaboro.com/open/kolaboro_verify.py, bundled unchanged.

They are not on npm or PyPI yet. Install them from kolaboro.com and check the hashes in
https://kolaboro.com/sdk/SHA256SUMS.

## JavaScript / TypeScript (browsers, Node 20+, Deno, Bun, Workers)

```js
import { Kolaboro } from 'https://kolaboro.com/sdk/kolaboro-0.1.0.mjs';   // or download it next to your code
const k = new Kolaboro();
const s = await k.stats();
console.log(s.projects, k.last.signature);          // { checked: true, ok: true, kid: 'kb-...' }
const bali = await k.projects({ market: 'Bali', min_public: 4 });
for await (const p of k.allProjects({ stage: 'off-plan' })) { /* every project, paged */ }
console.log((await k.verifyProject('BALI-014')).ok);  // Merkle proof recomputed locally
console.log((await k.auditLog()).ok);                 // whole public log re-verified: chain, checkpoint, inclusion, append-only
```

Types: https://kolaboro.com/sdk/kolaboro.d.ts. Pin the versioned file with Subresource Integrity (hash in manifest.json):

```html
<script type="module" integrity="sha384-..." crossorigin src="https://kolaboro.com/sdk/kolaboro-0.1.0.mjs"></script>
```

## Python 3.8+

```sh
pip install https://kolaboro.com/sdk/kolaboro-0.1.0-py3-none-any.whl
```

```python
from kolaboro import Kolaboro
k = Kolaboro()
print(k.stats()['projects'], k.last['signature'])
for p in k.all_projects(market='Dubai'):
    print(p['id'], p['score'], p['vscore'])
print(k.audit_log()['ok'])
```

No dependency. If the `cryptography` package is installed it is used for Ed25519, otherwise the RFC 8032 reference algorithm in
`kolaboro/_verify.py` is used (slower, same answers).

## Methods (same names in both, snake_case in Python)

stats, summary, projects(filters), allProjects / all_projects, projectsCsv, project(id), projectAt(id, day), markets, marketsCsv,
changes(since), freshness, evals, uptime, aiSpend, build, pdf(sha256), receipt(id), log, logInput, proof(id), logProof(day),
logConsistency(first, second), checkpoint() (note signature checked), verifyProject(id), auditLog(), json(path), text(path).

Filters for projects: market, country, stage (off-plan, under construction, completed), min_public (0 to 6), min_confirmed (0 to 6),
all_six, flags, limit (max 1000), offset.

Options: baseUrl, verify (default true), apiKey (optional key from https://kolaboro.com/api-keys/: calls go through the metered
endpoint /api/x/k/m/* and count against the key's daily quota), timeoutMs, retries, fetch, publicKeys.

## Tests

Both test suites run against production:

```sh
node --test sdk/src/js/test.mjs
cd sdk/src/python && python3 -m unittest discover -s tests
```

## Build

`sdk/src/build.sh` compiles `js/kolaboro.ts` with tsc, prepends kolaboro-verify.js unchanged, builds the wheel and writes
SHA256SUMS and manifest.json (SHA-256 and SRI sha384 of every file).
