invoance 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +4 -0
- data/lib/invoance/client.rb +13 -4
- data/lib/invoance/http.rb +10 -0
- data/lib/invoance/resources/audit.rb +30 -3
- data/lib/invoance/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5e2d35b71291d29aa248a149572823d79d968ed379130b206e2e60776fe892b9
|
|
4
|
+
data.tar.gz: 544522d6d2e329196e3586604cf4ffc86d7bcd8bd8fc183ae7827ce077b2793f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f2caf663d660ce5ce79deadff7a86d83e9cc2d3c20fc861c3b558bc8da24fcb776f6968e70e0481a1c9ae6e2e239afe9b8e3b00406ce4c83cdbe341bddce2b76
|
|
7
|
+
data.tar.gz: 75a63ff16bc063470049c9f24ff8195916cfdaaad90d87d28fda40ebbd96137bfd7ebc170bbf97a9b4284a7923c2a93fea0db67be3c378b5f6e60195181475f3
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-07-14
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `Client#validate` now probes the scope-free introspection endpoint
|
|
13
|
+
`GET /v1/me` instead of `GET /v1/events?limit=1`. Keys restricted to
|
|
14
|
+
`audit:*` scopes now validate correctly (the old events probe could 403
|
|
15
|
+
on a missing events scope and report a misleading reason). The return
|
|
16
|
+
shape (`"valid"` / `"reason"` / `"base_url"`) and the 401 / 403 / 429 /
|
|
17
|
+
network classifications are unchanged; only the 403 `reason` text changed —
|
|
18
|
+
it now describes an IP-access-rule block instead of a missing events
|
|
19
|
+
permission, since `/v1/me` requires no scope.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- `Client#me` — API-key introspection via `GET /v1/me`. Returns the raw
|
|
24
|
+
decoded response (organization, tenant, api_key with scopes, limits) as a
|
|
25
|
+
string-keyed `Hash`; raises like any other resource call.
|
|
26
|
+
- Audit org lifecycle methods on `audit.orgs`:
|
|
27
|
+
- `update(organization_id, name:)` — rename an org via
|
|
28
|
+
`PATCH /audit/orgs/:org_id`; pass `name: nil` to clear the name.
|
|
29
|
+
- `archive(organization_id)` / `unarchive(organization_id)` — idempotent
|
|
30
|
+
`POST /audit/orgs/:org_id/archive` and `.../unarchive`. Archiving freezes
|
|
31
|
+
new activity while history stays verifiable.
|
|
32
|
+
- `delete(organization_id)` — hard delete via `DELETE /audit/orgs/:org_id`;
|
|
33
|
+
raises `ConflictError` (`org_not_deletable`) when signed history would be
|
|
34
|
+
destroyed.
|
|
35
|
+
- `audit.orgs.list(include_archived: true)` — include archived orgs in
|
|
36
|
+
listings (excluded by default). Org responses now carry `archived_at`
|
|
37
|
+
(RFC 3339 string or `nil`).
|
|
38
|
+
- `PATCH` support in the HTTP transport.
|
|
39
|
+
|
|
8
40
|
## [0.1.0] - 2026-07-06
|
|
9
41
|
|
|
10
42
|
### Added
|
data/README.md
CHANGED
|
@@ -53,6 +53,10 @@ puts event["event_id"]
|
|
|
53
53
|
# Verify the API key / connectivity (never raises)
|
|
54
54
|
result = client.validate
|
|
55
55
|
raise "bad config: #{result["reason"]}" unless result["valid"]
|
|
56
|
+
|
|
57
|
+
# Introspect the key — org, tenant, scopes, limits (GET /v1/me; raises on error)
|
|
58
|
+
whoami = client.me
|
|
59
|
+
puts whoami["api_key"]["scopes"]
|
|
56
60
|
```
|
|
57
61
|
|
|
58
62
|
Responses are plain Ruby `Hash`es with **string keys** matching the wire JSON
|
data/lib/invoance/client.rb
CHANGED
|
@@ -53,14 +53,23 @@ module Invoance
|
|
|
53
53
|
@config.base_url
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
#
|
|
57
|
-
#
|
|
56
|
+
# Introspect the API key via GET /v1/me. Requires no scope, so it works
|
|
57
|
+
# for any valid key. Raises like every other resource call.
|
|
58
|
+
#
|
|
59
|
+
# @return [Hash] { "valid" =>, "organization" =>, "tenant" =>,
|
|
60
|
+
# "api_key" =>, "limits" => } (string keys, wire JSON as-is)
|
|
61
|
+
def me
|
|
62
|
+
@http.get("/me")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Call the scope-free introspection endpoint (GET /v1/me) to confirm
|
|
66
|
+
# the API key works. NEVER raises.
|
|
58
67
|
#
|
|
59
68
|
# @return [Hash] { "valid" =>, "reason" =>, "base_url" => }
|
|
60
69
|
def validate
|
|
61
70
|
base = @config.base_url
|
|
62
71
|
begin
|
|
63
|
-
|
|
72
|
+
me
|
|
64
73
|
{ "valid" => true, "reason" => nil, "base_url" => base }
|
|
65
74
|
rescue AuthenticationError
|
|
66
75
|
{ "valid" => false,
|
|
@@ -68,7 +77,7 @@ module Invoance
|
|
|
68
77
|
"base_url" => base }
|
|
69
78
|
rescue ForbiddenError
|
|
70
79
|
{ "valid" => true,
|
|
71
|
-
"reason" => "API key authenticated but
|
|
80
|
+
"reason" => "API key authenticated but the request was blocked (IP access rules)",
|
|
72
81
|
"base_url" => base }
|
|
73
82
|
rescue QuotaExceededError
|
|
74
83
|
{ "valid" => true,
|
data/lib/invoance/http.rb
CHANGED
|
@@ -59,6 +59,16 @@ module Invoance
|
|
|
59
59
|
handle(resp, ctx)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# PATCH returning parsed JSON.
|
|
63
|
+
def patch(path, body = nil)
|
|
64
|
+
uri = build_uri(path)
|
|
65
|
+
ctx = { method: "PATCH", path: path }
|
|
66
|
+
req = Net::HTTP::Patch.new(uri)
|
|
67
|
+
req.body = JSON.generate(body) unless body.nil?
|
|
68
|
+
resp = do_request(req, uri, ctx, headers: @base_headers)
|
|
69
|
+
handle(resp, ctx)
|
|
70
|
+
end
|
|
71
|
+
|
|
62
72
|
# DELETE returning parsed JSON.
|
|
63
73
|
def delete(path)
|
|
64
74
|
uri = build_uri(path)
|
|
@@ -107,9 +107,36 @@ module Invoance
|
|
|
107
107
|
@http.post("/audit/orgs", body)
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
# GET /audit/orgs
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
# GET /audit/orgs — archived orgs are excluded unless
|
|
111
|
+
# include_archived: true is passed.
|
|
112
|
+
def list(include_archived: nil)
|
|
113
|
+
@http.get("/audit/orgs", { "include_archived" => include_archived })
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# PATCH /audit/orgs/:org_id — rename. Pass name: nil to clear the
|
|
117
|
+
# name (sends JSON null).
|
|
118
|
+
def update(organization_id, name:)
|
|
119
|
+
@http.patch("/audit/orgs/#{organization_id}", { "name" => name })
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# POST /audit/orgs/:org_id/archive — idempotent. Freezes new
|
|
123
|
+
# activity (ingest/streams/portal/exports return 409 org_archived);
|
|
124
|
+
# history stays verifiable.
|
|
125
|
+
def archive(organization_id)
|
|
126
|
+
@http.post("/audit/orgs/#{organization_id}/archive")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# POST /audit/orgs/:org_id/unarchive — idempotent.
|
|
130
|
+
def unarchive(organization_id)
|
|
131
|
+
@http.post("/audit/orgs/#{organization_id}/unarchive")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# DELETE /audit/orgs/:org_id — hard delete, allowed only when
|
|
135
|
+
# nothing signed would be destroyed (never-ingested org, or
|
|
136
|
+
# archived + retention fully purged). Raises ConflictError
|
|
137
|
+
# (org_not_deletable) otherwise.
|
|
138
|
+
def delete(organization_id)
|
|
139
|
+
@http.delete("/audit/orgs/#{organization_id}")
|
|
113
140
|
end
|
|
114
141
|
|
|
115
142
|
# GET /audit/orgs/:org_id/integrity
|
data/lib/invoance/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: invoance
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Invoance, Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|