> For the complete documentation index, see [llms.txt](https://docs.j.tools/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.j.tools/help-and-security/model.md).

# Our security model

J Tools runs your token operations without ever taking custody of your wallet. You sign every transaction yourself, the platform builds and broadcasts it, and server-side guards sit behind all of it.

```mermaid
flowchart LR
    A[You set up an action in J Tools] --> B[Your wallet shows the transaction]
    B --> C[You approve and sign in your own wallet]
    C --> D[Signed transaction is broadcast to Solana]
    C --> E[Your keys never leave your wallet]
    class C,E brand;
    class A,B,D soft;
    classDef brand fill:#EF2A2A,stroke:#EF2A2A,color:#ffffff,font-weight:bold;
    classDef soft fill:#1f2937,stroke:#374151,color:#e5e7eb;
```

{% hint style="success" %}
**J Tools is non-custodial.** We never hold your private keys and never ask for them. Every transaction is built in your browser and signed by your own wallet. If any page ever asks you to paste a private key, stop, close it, and let us know.
{% endhint %}

## The short version

{% hint style="success" %}
Your keys stay in your wallet, the browser is never trusted to set a number about money, and secrets never reach the logs. Admin access is locked behind a second factor, and the audit trail is built so any tampering shows.
{% endhint %}

## The promises at a glance

<table data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td></td><td></td><td></td></tr></tbody></table>

## Non-custodial by design

J Tools never stores, requests, or transmits a private key. Every signature happens in your browser through your wallet adapter, and only the signed result goes to the network. If a page ever asks you to paste a private key or seed phrase, that is not us.

## A tamper-evident audit chain

Admin actions are written to an append-only audit log. Each row carries a `prev_hash` that is the SHA-256 of the row before it, so the entries are linked like a chain. Change or delete one row and every hash after it stops matching, which makes the edit obvious. Log payloads never contain passwords or tokens.

## RPC whitelist and rate limits

The browser does not talk to a raw Solana node. It goes through a read proxy that allows only a fixed set of methods and caps requests per IP. RPC URLs and keys stay server-side, so the browser has nothing to leak. Rate limits are stored in Postgres and applied per endpoint, and the real client IP is read from the rightmost `x-forwarded-for` value so the limit cannot be spoofed with a forged header.

## Fee-theft protection

When a tool charges a platform fee, the commission is recorded against the amount the database holds, never a number the browser sends. No path trusts a client-supplied fee. You see the full breakdown (total, platform fee, and estimated network fee) on the tool's fee card before you confirm anything. For the reference values, check the in-app fee summary or the [fee schedule](/reference/fee-schedule.md).

{% hint style="warning" %}
**About fees.** Every action has two costs: the Solana **network fee** paid to validators, and the **J Tools platform fee**. The platform fee always shows in the app before you confirm, and nothing is charged until you sign. Fees can change over time, so trust the in-app summary rather than a number you saw once.
{% endhint %}

## Admin access is locked down

Reaching the admin panel takes a password and a TOTP code, enforced on the server. The flow is built to give nothing away.

{% tabs %}
{% tab title="Second factor" %}
TOTP is mandatory. Codes are checked server-side, and a run of wrong codes locks the account for a cool-down window. The lock reason is never sent back to the client.
{% endtab %}

{% tab title="Password storage" %}
Admin passwords are stored as Argon2id hashes, configured through environment variables only. There is no password-reset screen in the panel or the API; a change means a new env value and a deploy.
{% endtab %}

{% tab title="No information leak" %}
A failed login always returns the same generic message in constant time. Whether the username is wrong, the password is wrong, or the account is locked, the response looks identical from the outside. Login attempts are rate-limited by both IP and username.
{% endtab %}

{% tab title="Sessions" %}
Sessions live in a server-side store with httpOnly, Secure, SameSite=Strict cookies and cryptographically random IDs. They rotate on login to defend against fixation, time out when idle, and are capped per admin.
{% endtab %}
{% endtabs %}

## OPSEC everywhere

Operational security is a standing rule across every endpoint and page. Secrets, private keys, and full tokens are never logged. A client error response is a plain `{ code, message }` with no stack trace, no internal path, and no database detail; the full picture stays in server logs. Publishing through automated agents is gated behind human admin approval, so nothing reaches readers without a person signing off.

## FAQ

<details>

<summary>Does J Tools ever see my private key?</summary>

No. Signing happens in your wallet, in your browser. The platform only receives the signed transaction, never the key behind it.

</details>

<details>

<summary>Why can't I see the RPC endpoint the app uses?</summary>

RPC URLs and keys are server-only secrets. The browser routes its reads through a proxy, so there is no public RPC variable to expose. That keeps the provider credentials out of reach.

</details>

<details>

<summary>What stops someone from faking a smaller fee?</summary>

Nothing the browser sends about a fee is trusted. The commission record always uses the amount stored in the database, so a tampered client value changes nothing. See Fee protection.

</details>

<details>

<summary>How would I know if the audit log was edited?</summary>

Each entry's hash depends on the one before it. Editing any row breaks every hash that follows, which makes the change detectable on a verification pass.

</details>

## Related pages

{% content-ref url="/pages/N0Wec9bomiVBhdWDLBao" %}
[Phantom warnings explained](/help-and-security/phantom-warnings.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.j.tools/help-and-security/model.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
