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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ adjudicate fiqh and will not become a court with a merge button. Attest your own
locally — `keel assets attest` writes to *your* database, with your source and your name on
it — and run the enforcement engine under it. The disagreement then costs nobody anything:
upstream stays neutral, your deployment follows your ruling, and the audit trail records
exactly who said what.
exactly who said what. The Shariah reasoning the codebase encodes, ruling by ruling with its
source, is written up in [`docs/fiqh-basis.md`](docs/fiqh-basis.md).

## Development setup and the gates a PR must pass

Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ applies the confirm/autonomy gate, then places and logs. There is deliberately n
promotion clears a two-part gate: performance floors *and* an overfitting check
(PBO/CSCV). A rule that clears four floors on one in-sample parameter set is exactly what
the second gate exists to be suspicious of.
- **The rails** (`keel/execution/guards.py`) — nineteen deterministic checks no order can
- **The rails** (`keel/execution/guards.py`) — eighteen deterministic checks no order can
skip and nothing can override, not even autonomy: the halal allowlist, per-order and
per-day spend caps, exposure and concentration caps, correlation-aware sizing, a
minimum-move floor, no-martingale/no-stop-widening, a fails-closed kill-switch, total and
Expand Down Expand Up @@ -96,7 +96,7 @@ the stop holds, not what you spend.
```
keel/ the agent and CLI
├── agent.py the loop and RULE_REGISTRY (where rules live)
├── execution/guards.py the 19 rails (where enforcement lives)
├── execution/guards.py the 18 rails (where enforcement lives)
├── execution/sizing.py position sizing
├── compliance/screen.py attested allowlist admission (fails closed)
└── commands/ CLI command implementations
Expand All @@ -118,6 +118,9 @@ adapter, deliberately divergent, that the conformance suite runs against.

## Documentation map

- [`docs/fiqh-basis.md`](docs/fiqh-basis.md) — the Shariah reasoning keel encodes, ruling by
ruling, each with its in-repo source: what is attested vs computed, the open questions,
and how to disagree.
- [`docs/operator-runbook.md`](docs/operator-runbook.md) — operating a deployment: the
account-level compliance obligations no rail can enforce, deploying/upgrading releases,
and the paper-vs-live distinctions (two accounts that share nothing).
Expand Down
255 changes: 255 additions & 0 deletions docs/fiqh-basis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
# The fiqh basis of keel's encoded rulings

## What this document is and is not

This document is written for a Muslim developer deciding whether to trust keel with money. It
states, ruling by ruling, what Shariah reasoning is encoded in this repository, and where in
the repository each ruling's source lives — so the basis is auditable by someone who does not
already know where to look. It is scholarship by reference: every ruling below carries a
citation to an in-repo source, and the enforcement code carries the same citations in its
comments.

What this document is not: a fatwa, or a claim that keel can produce one.

> keel is not a fatwa engine. It is an enforcement engine for a ruling you supply.

No scholar has reviewed this document; whether such a review happens is deliberately a
separate, still-open question (#289), and nothing here should be read as one having occurred.

## How to read the citations

`§N.x` means source N, section x → the file
`docs/superpowers/references/trading-knowledge-base/sources/source-NN.md`, section `N.x` —
the knowledge base's own convention, stated in its README index. The sources are extracts of
real books, papers, and council resolutions, kept in-repo; the README row for each source
records what was fetched and from where, so a claim is checkable against its origin.

Two honesty rules the knowledge base holds, and this document inherits:

- Where a source is silent on something, we say "not stated" — a gap is never papered over
with a paraphrase that sounds like a ruling.
- Where schools and councils disagree, the disagreement is named, with both sides — never
flattened into "scholars say". §71.7/§71.8's opinion map is the worked example:
prohibitions, permissions, and the conditions each attaches, all recorded.

## What is attested versus what is computed

The core claim of keel's compliance design, in the screen's own words
(`keel/compliance/screen.py`): market facts are computed, Shariah classifications are
**ATTESTED, never inferred**. Whether a token's core purpose is a haram sector (§28.4),
whether it is asset-backed `'ayn` or a claim `dayn` (§65.5/§67.2), and whether it pays a
riba-like yield are questions of fact-plus-scholarship about the world. No module in this
repository derives them from candles, and none pretends to. A human records them, with a
source and a name, via `keel assets attest`.

And when the attestation is absent: **unknown is a rejection**. An unattested asset is not
"probably fine" — it is unknown, and the screen fails closed on unknown. The same posture
runs through the rails: rail 17 fails closed on a missing attestation because "silence is not
evidence of possession" (`keel/execution/guards.py`).

## The rulings encoded, and their sources

### The curation screen (`keel/compliance/screen.py`)

A CURATION gate — admission to the allowlist, checked once, not per-trade. §28.4 is explicit
that sector and backing are "a listing criterion, checked once when curating the allowlist,
not per-trade". The attested axes:

- **Sector (§28.4).** A token whose core business is a haram line — gambling, alcohol,
riba-based lending, and the rest of `HARAM_SECTORS` — is rejected. Aave/Compound-class
lending tokens fail here (§41.1's readings, confirmed at §65.10).
- **Backing (§65.5/§67.2).** `'ayn` (an owned thing) passes; `dayn` (a debt claim on an
issuer) is refused — trading a pure claim is a different contract under different rules.
An `'ayn` asset backed by gold or silver draws a warning that §65.5's stricter
`bay' al-sarf` regime applies: no deferment, and a 72-hour settlement bound.
- **`pays_yield` (§28.4, the riba screen).** Rejects with the screen's exact failure wording:
"the asset carries a guaranteed/expected return for holding it, which is riba-like
(§28.4); holding it is not a bare spot position". The field's semantics are BARE HOLDER,
not "staking exists": it asserts what holding the asset *without* staking or lending earns.
Established by fetching the docs, not by assumption — Solana's staking documentation says
rewards require delegation ("In order to earn staking rewards … the tokens in a stake
account must be delegated to a validator"), with no rebasing, so "Bare holding earns
nothing, which is exactly what the field asserts."
(`docs/experiments/2026-08-07-unvalidated-skip-set-reassessment.md`).
- **Wrapper/instrument (§71.4a).** The allowlist is not juristically homogeneous, so admission
names the CONTRACT, not just the underlying. Only `spot` is admitted; CFD, future,
perpetual, option, and leveraged-token listings are refused, recorded via
`keel assets attest-instrument`. Unattested fails closed.

The computed axes — history depth, liquidity, settlement quotability — are market facts
about our own cache, recomputed freely. Of everything the screen checks, a documented
exception (`keel assets exempt`) may waive only ONE criterion today: `history`
(`WAIVABLE_CRITERIA` is `frozenset({"history"})`). Liquidity, settlement, and the spot
instrument shape can NEVER be waived, and neither can any Shariah criterion — nothing in
the screen consults a waiver for them, and the CLI's `--criterion` choice is restricted to
that set. Expanding it is a deliberate future decision, not a default.

### Rail 1 — allowlist enforcement (`keel/execution/guards.py`)

Per-trade and un-overridable: every intent, DCA included, must be for an allowlisted asset.
This rail enforces the attested rulings above mechanically on every order; the ruling itself
lives in the attestation, never in the rail.

### Rail 17 — withdrawal capability, `qabd` §65.4

The one rail that encodes fiqh as an executable check. Ayub's constructive-possession test
holds that possession is completed when the vendor sets the asset aside and "there is nothing
to prevent the buyer from taking physical possession from the vendor whenever he desires";
the two-part test is "(i) the buyer bears the risk and reward, and (ii) nothing prevents the
buyer from taking delivery whenever he wishes" (§65.4). An asset we cannot withdraw is an
asset we may not validly POSSESS — so acquiring more of it is the thing to stop.

The operative test is tri-sourced: "Three sources now converge on the identical operative
test: possession is the ability to dispose, not physical custody (§65.4 Ayub · §67.1 OIC
53/4-6 · §71.5 AAOIFI SS 18 3/5 via SRB)" — §71.5's own summary; §67.1 is Al-Jarhi,
Abuzaid & Oweida's *Handbook of Islamic Finance* (2022) quoting the OIC Fiqh Academy
resolution (Res. 53/4-6) that holds electronic constructive possession sufficient.

Mechanics: the operator attests with `keel withdrawals attest`; the attestation is live-read
on every intent and expires after 7 days (`WITHDRAWAL_ATTESTATION_TTL_SEC`,
`keel/execution/executor.py`) — "a stale attestation is no better than none". ENTRIES ONLY,
like rails 11/16: existing holdings are already ours, and forcing a sale to "fix" a
withdrawal freeze would be strictly worse than holding through it. Unknown fails closed.

### Rails 18/19 — settlement currency and spot-instrument shape

Charter, not fiqh-derivation: "Spot-only is this agent's CHARTER, not an operator preference"
(`guards.py`, rail 19's comment). Rail 18 confines settlement to the operator's configured
currencies (default USD/USDC — a config field, the escape hatch); rail 19 requires the
product id to be a well-formed spot pair. Both are justified by measurement, not doctrine:
the feasibility study `docs/experiments/2026-08-05-coinbase-asset-class-feasibility.md`
verified by execution which instrument classes exist on the venue and what each rail closes.
The fiqh content — that derivatives and difference-settlement are impermissible — is real
(§65.6: what makes speculation *maisir* is non-ownership, non-delivery, difference-settlement)
but the RAILS are the charter enforcing it.

### Purification (§65.9) and idle-balance rewards (§56.3)

`keel/compliance/purification.py` implements Ayub §65.9: interest/reward credits are
segregated from realised P&L and the equity base, reported as owed to charity, never
recognised as profit — and zakat is computed on purified wealth (§33.1). It is REPORT-ONLY:
the agent never disposes of funds. The record of what it found in this project's own imported
history is `docs/experiments/2026-07-20-income-purification.md`.

The preventive half is §56.3: Coinbase pays USDC rewards on idle balances, that interest is
riba, and it accrues with no order placed — so no rail can catch it. Disabling rewards at the
account level is the operator's obligation, listed first in
`docs/operator-runbook.md`.

### The remaining rails — prudential, not fiqh

Eighteen rails exist (1–14, 16, 17, 18, 19 — there is no rail 15). Of these, only rail 17
encodes a fiqh ruling, and rails 1/18/19 enforce what the screen and the charter admit. The
rest are PRUDENTIAL — risk and discipline, justified by trading evidence, carrying no
religious claim:

| rail | what it does | basis |
| --- | --- | --- |
| 2, 3 | per-order and per-day spend caps | risk discipline |
| 4, 5, 6 | exposure cap, correlation-aware sizing, concentration cap | risk discipline |
| 7 | min-move / anti-scalping floor | trading justification only — see below |
| 8, 9 | no averaging into losers, no stop-widening | risk discipline |
| 10 | sells must cite a defined rule | audit discipline |
| 11, 16 | drawdown and consecutive-loss breakers | risk discipline |
| 12 | stale-feed + kill-switch, fails closed | operational safety |
| 13, 14 | spend only the settled quote currency; monthly allowance cap | operational safety |

Rail 7 carries a correction this repository records prominently: §65.6 holds that
"speculation per se, which means sale/purchase keeping in mind possible change in prices in
the future, is not prohibited" — what makes speculation *maisir* is non-ownership,
non-delivery, or difference-settlement, **not frequency**. So the anti-scalping rail "keeps
its trading justification and LOSES its shariah claim" (the KB's words for §65.6). It stays
because churn costs taker fees, not because churn is haram.

## What keel deliberately does not decide

- **Whose ruling is right.** The ruling lives in your attestation, not in the code, so two
operators following different schools get different answers from the same code, by design
(see `CONTRIBUTING.md`, "Governance: rulings vs. machinery").
- **Whether a given token qualifies as *Māl*.** That is a judgement of fact-plus-scholarship
the screen defers to the human attestor — the DOGE question below is the live example.
- **School differences.** Where sources diverge (§66.6 records identical retail FX ruled
haram by one jurisdiction and halal by another), keel records both and enforces whichever
ruling the operator supplies; it does not adjudicate.
- **Anything about an asset nobody has attested.** Unknown is a rejection, not a default
pass — refusing to decide is the decision.

## Known open questions

Stated, not hidden — each is a place where keel's encoded behaviour could be wrong:

- **ATOM dilution.** Cosmos Hub's own documentation (docs.cosmos.network) says: "Delegate
your ATOM to one or more of the validators on the Cosmos Hub blockchain to earn more ATOM
through Proof-of-Stake"; and, per stakingrewards.com/asset/cosmos as examined at the
time, ATOM has no supply cap, and its dynamic inflation rate adjusts algorithmically to
target the staking ratio (~12.66% inflation, ~19.49% staking APY as of 2026-08-14, the
date of examination). Inflation is uncapped and
dynamic, and newly minted ATOM accrues only to bonded delegators — so a bare holder is
structurally diluted, at an algorithmically maintained rate: value transfers from
non-stakers to stakers, and the transfer does not fade. `pays_yield=NO` remains correct on
the screen's own axis (bare holding pays nothing) and is a separate question from this one.
There is no settled answer in this repository.
- **Staking generally (§65.14).** Contested, not settled: the honest position is "the
question is genuinely contested, we have no scholarly determination in hand, our mandate has
no need of it, and §29.2 directs us to the conservative branch where scholars diverge."
keel stakes nothing — no module in this repository can stake, so no code excludes staked
positions — which is why the §29.2 conservatism belongs to the premise question below,
not to an exclusion keel performs. Stop implying staking is settled riba.
- **The foundational premise itself (§71.1/§29.2).** Every ruling above presupposes that
crypto is Shariah-recognised tradable property, and on that the highest available
authority has declined to rule. IIFA Resolution 237 (§71.1) convened a dedicated symposium
on electronic currencies, debated the matter at its 24th session (Nov 2019), and ISSUED
NO RULING — it identified as unresolved exactly this question ("Is cryptocurrency
considered by Shariah a real-valued property and a tradable item?"), noted the
significant risks and the instability of their transactions, and referred the matter back
for further research. A withheld ruling is not a prohibition; it is also not a
permission. keel's premise that BTC/ETH-class assets are tradable property is a
well-supported INTERPRETIVE POSITION held on §29.2's conservative branch, not a settled
ruling — and keel does not get to cite the same Academy's Res. 53/4-6 as authoritative
on `qabd` (§67.1) while treating it as silent here.
- **DOGE (§86.4).** "A token that has no genuine use or benefit and survives only because
people hope to sell it to someone else at a higher price may FAIL to qualify as *Māl*" —
and the source's own lean is "Strong lean: EXCLUDE DOGE." DOGE also has no supply cap.
Whether "no underlying purpose" is disqualifying "is exactly the kind of judgement the
screen defers to a human" (`docs/experiments/2026-07-20-candidate-universe.md`) — deferred,
not decided.
- **ZEC and the rest of the deferrals.** The candidate-universe record lists the open
questions the attestation step has to answer and "which this agent must not answer".

## How to disagree

The route the architecture already provides — record your own ruling locally:

- **Attest your own classification.** `keel assets attest --asset --sector --backing
--pays-yield --source --attested-by` writes to *your* database; `--source` and
`--attested-by` are required, because an unsourced claim is not evidence. Your deployment
then follows your ruling, upstream stays neutral, and the audit trail records exactly who
said what.
- **Document exceptions where the screen allows them.** `keel assets exempt` may waive only
one criterion today — `history`: never a Shariah criterion, and never liquidity,
settlement, or the spot instrument shape.
- **To change a classification for everyone**, that is a PR of a different kind:
`CONTRIBUTING.md` requires a cited source and discussion before merge — a classification
with no source behind it is not mergeable, however confident the author.

## Sources index

- `docs/superpowers/references/trading-knowledge-base/sources/source-65.md` — Muhammad Ayub,
*Understanding Islamic Finance* (Wiley 2007): the foundation source (§65.4 `qabd`, §65.5
backing, §65.6 speculation, §65.9 purification, §65.14 staking).
- `docs/superpowers/references/trading-knowledge-base/sources/source-67.md` — Al-Jarhi,
Abuzaid & Oweida, *Handbook of Islamic Finance* (ASBÜ Yayınları, 2022), quoting OIC Fiqh
Academy Res. 53/4-6 on electronic constructive possession (§67.1), gold/`sarf` (§67.2).
- `docs/superpowers/references/trading-knowledge-base/sources/source-71.md` — IIFA Res. 237,
SRB (AAOIFI SS 18 3/5), SC Malaysia's `ribawi` classifier (§71.4a), digital `qabd` (§71.5).
- `docs/superpowers/references/trading-knowledge-base/sources/source-85.md` — Mufti Faraz
Adam, *Bitcoin: Shariah Compliant?* — the keystone for the BTC/ETH premise.
- `docs/superpowers/references/trading-knowledge-base/sources/source-86.md` — Mufti Faraz
Adam, *Is Crypto Halal?* — *Māl* qualification and the DOGE reading (§86.4).
- `docs/superpowers/references/trading-knowledge-base/README.md` — the index: per-source
rows, the citation convention, and the opinion maps.
- Experiment records cited above, under `docs/experiments/`:
`2026-08-07-unvalidated-skip-set-reassessment.md` (bare-holder semantics),
`2026-07-20-candidate-universe.md` (deferred questions),
`2026-07-20-income-purification.md` (what purification found),
`2026-08-05-coinbase-asset-class-feasibility.md` (rails 18/19).
Loading
Loading