# D-Bus API: `org.liberux.CallLog1`

## Bus, service and path

| Item            | Value                        |
| --------------- | ---------------------------- |
| Bus             | Session bus (per-user)       |
| Well-known name | `org.liberux.CallLog1`       |
| Object path     | `/org/liberux/CallLog1`      |
| Interface       | `org.liberux.CallLog1`       |
| Activation      | D-Bus user service unit (`data/org.liberux.CallLog1.service`) and a systemd `Type=dbus` user unit. |

Single-instance per user. ATL and native Liberux apps talk to the same instance.

## Design philosophy

Typed by entity, not a SQL pass-through — same rationale as `contacts-server`.
The call-log row is small and fixed-shape, so it rides as a struct rather than
an `a{sv}` dict.

## `Call` struct

D-Bus signature: `(usxxibs)` — `(id, number, date, duration, type, new, cached_name)`.

| Field         | Type | Notes                                                       |
| ------------- | ---- | ---------------------------------------------------------- |
| `id`          | `u`  | `calls._id`.                                               |
| `number`      | `s`  | May be empty (withheld number).                            |
| `date`        | `x`  | Call start, ms since the Unix epoch.                       |
| `duration`    | `x`  | Talk time in whole seconds; 0 if unanswered.               |
| `type`        | `i`  | `CallLog.Calls.TYPE` (see `schema.md`).                    |
| `new`         | `b`  | Unread flag.                                               |
| `cached_name` | `s`  | Name snapshot at insertion; empty if the caller was unknown. |

## Error model

D-Bus errors in the `org.liberux.CallLog1.Error.*` namespace:

| Error name                                    | Meaning                          |
| --------------------------------------------- | -------------------------------- |
| `org.liberux.CallLog1.Error.NotFound`         | Referenced id does not exist.    |
| `org.liberux.CallLog1.Error.InvalidArgument`  | Caller-supplied data is invalid. |
| `org.liberux.CallLog1.Error.Internal`         | DB or I/O error.                 |

## Methods

All on `/org/liberux/CallLog1`, interface `org.liberux.CallLog1`.

### `AddCall( s number, x date, x duration, i type, s cached_name ) → u id`

Records a finished call and returns the new `calls._id`. `cached_name` may be
empty. Emits `Changed`.

### `QueryRecent( u limit ) → a(usxxibs)`

Returns the most recent calls newest-first (by `date`, then `_id`). `limit = 0`
returns every row.

### `GetCall( u id ) → (usxxibs)`

Returns one call. Errors `NotFound` if absent.

### `DeleteCall( u id )`

Deletes one call. Errors `NotFound` if absent. Emits `Changed`.

### `DeleteAll()`

Clears the whole log. Emits `Changed`.

### `MarkAllRead()`

Clears the `new` flag on every call (missed-call badge reset). Emits `Changed`.

## Signals

### `Changed()`

Fired after any mutation. Carries no payload — observers refresh whatever query
they are watching. Consumers translate this into Android
`ContentObserver.onChange()` (via ATL) or a UI reload.

## Permissions

v1 ships without any permission check; a single `permission_gate( method )` hook
returns `Ok(())` unconditionally, ready for a future polkit wiring.

## Stability and versioning

`org.liberux.CallLog1` is the v1 surface. Breaking changes will use a new
interface name (`CallLog2`) on the same path; additive changes (new methods, new
trailing struct fields) do not bump the version.
