Releases: forwardnetworks/forward-python-sdk
Release list
v0.1.16
[0.1.16] - 2026-09-17
Added
- Raw snapshot artifacts, unpublished:
client.snapshots.files(snapshot_id)
lists every file Forward stored for a snapshot, and.file(snapshot_id, file_name)reads one -- unlike a device's own files, these need not belong
to a modeled device, useful for cloud integrations needing artifacts such as
GCP'scloud_instances.gen. Closes a gapdocs/snapshots.mdhad documented
by name (client.snapshots.files/.file) since it was written; verified
live by listing and reading a real collected file, and confirming an unknown
name 404s asForwardNotFoundError.
v0.1.15
[0.1.15] - 2026-09-16
Added
- Connectivity tests, unpublished:
client.connectivity_testsstarts and stops
an on-demand reachability/authentication probe against a classic device or a
network endpoint (start/stop, one name or aDeviceSet, dispatched to
the endpoint variant by a fixed query on the same path), reads the result
Forward already publishes for scheduled collection (SourceConnectivityResult),
and reads the same result broken into its six phases -- connection,
authentication, type discovery, setup, authorization, query -- each a
discriminated union generated as aRootModel, sophase.rootgets the
concrete phase. Requested by the change-demo integration, which found the
GUI's "Test connectivity" button backed by no SDK surface at all. Verified
live: a device tested end to end through all six phases, an endpoint tested
through the dispatched variant, both singly and in bulk; nothing is left
behind since starting or stopping a test never touches a snapshot.
v0.1.14
[0.1.14] - 2026-09-12
Added
- Security analysis, unpublished and previously undocumented: security zones
(client.security_zones), full CRUD over saved security-matrix filters and
running the matrix itself (client.security_matrix_filters,
client.security_matrix), resource-pool analysis and pairwise connectivity
(client.resource_pools), blast radius including the host-centric variant
and its XLSX report (client.blast_radius), and internet exposure with the
per-scanner exposed-hosts listing (client.internet_exposure). Resource
pools are a new three-way discriminated union (DEVICE_ZONE/ON_PREM/
CLOUD); blast radius reuses the publishedLocationFilterunion already
in the SDK. Verified live: filter created, matrix run, deleted; blast radius,
resource-pool analysis, and internet exposure read on the local instance's
real snapshot; the XLSX report streamed and its bytes confirmed as a genuine
workbook. - Dashboards and NQE panels, unpublished:
client.dashboards(list, defaults,
create, get, update with a whole-layout replace, delete, remove panels from
every dashboard, display settings) andclient.nqe_panels(list with usage,
create, patch, delete one or many, metric values and a metric preview over an
execution's result). Requested by the change-demo integration in its fourth
report. Shapes from Forward's controllers; verified live with a dashboard and
a panel created, embedded, unembedded and deleted. The metric-value reads are
gated by an org property an org admin cannot set, so those two were verified
against the source rather than a live instance. execution.result_key(): theR_key naming an execution's result, which
the metric reads take. Forward's published execution status omits it; the
variant its UI reads (?for=ui) carries it.- Synthetic devices, the unpublished remainder:
backdate_*on every family
(apply staged changes to an existing snapshot, invalidating it),
compute_*_connectionson the families that accept an NQE query
(a preview of what the query produces, with failure in the body),
l2vpns.add_l2_vpns(batch add), and
internet_node.get_internet_connection_suggestions. Two families had no
published surface at all: adjacent networks (client.adjacent_networks, full
CRUD and connection filtering) and T-API optical containers
(client.tapi_network_containers, hand-written because a container is
created from uploaded documents). Verified live in a scratch network that
was deleted afterwards; the backdate routes were confirmed to reach their
handlers without invalidating anything.
Fixed
-
device_tags.list()returned["tags"]. Forward wraps the listing as
{"tags": [...]}, published in the description, and the SDK read the payload
as a list, which yielded the envelope's keys. Both forms, with and without
devices, now return the tag records. -
device_tags.add_to_devices()andremove_from_devices()sent a bare array.
Forward takes{"devices": [...]}, also published, and refused with "Cannot
deserialize value of type DeviceSet from Array value". Both reported by the
change-demo integration in its fourth report. Verified live with a tag
created, applied to a device, removed and deleted.Both had tests, and both tests asserted the wrong shape, because fixture and
parser were written from one assumption. The description had the right shape
all along; nothing compared the SDK's bodies to it.
Changed
- The conformance test now validates the request bodies that hand-written
builders assemble against the declared schema, structurally: type, key
names, required keys the builder is responsible for, and enumerations the
builder chose. Bodies had been excluded on the grounds that a synthesized
payload proves nothing about content, which is true and beside the point: an
array where the description declares an object is wrong whatever it holds.
Reverting the device-tag builder makes the new check fail, so it would have
caught this on the first release.
0.1.13
Added
- Deployment configuration on
client.configuration: list every deployment
property, and read, set or clear one. The third scope beside org and
global, and the only route to properties such asOUTBOUND_CONNECTIONS,
which gates webhook creation, andPROBE_LLM_AVAILABILITY, which makes
Forward AI appear on a self-hosted deployment. Keys come back in upper case
here, unlike the org routes;config_value()reads either. Verified live,
including a write of a property's current value back to itself. Reported by
the change-demo integration as the last item of its third report.
0.1.12
Fixed
-
nqe.repo.publishwith a dry run refused every clean change. Forward's dry
run returnsnewErrorsas a map from every path examined to that path's
diagnostics, and a path that compiles maps to an empty list; the SDK read the
map's size as an error count, so a changed query that compiled was refused as
"1 new error". The recommended path, dry run before commit, could therefore
not publish a changed query at all. Older than any of the reports: the line
dates from the NQE layer's first commit, and its test fixture was a list, the
shape the parser believed, so the two agreed while both were wrong.Diagnostics are now read by severity, as Forward's own commit dialog reads
them: anERRORrefuses the publish and puts Forward's message and the path
in the exception, since diagnostics like "Mismatched input 'this'. Reminder:
record fields are comma-separated." are what the caller needs to see; a
WARNINGdoes not block and is returned onCommitReport.warnings. Verified
live: a broken edit is refused quoting the diagnostic with no draft left and
the library unchanged. Reported by the change-demo integration in its third
report, found while verifying the previous fix.
Added
devices.upsert_classic(), which runs Forward's batch upsert and then reads
the same names back, returning the devices as stored. The upsert itself
answers 201 with nothing worth reading, so confirming what was written took a
second call every consumer had to write. Verified live; a second run with the
same manifest returns the same devices.
0.1.11
Fixed
nqe.repo.dry_rundrops paths with nothing staged and retries, exactly as
commitdoes. A dry run is the same request with a flag and Forward refuses
it for the same reason, sopublish(dry_run_snapshot_id=...)raised on an
unchanged corpus wherepublish()alone reported it. The documented
recommendation to dry-run before publishing and the no-op case could not be
used together. Reported by the change-demo integration in its third report
and verified live: 23 unchanged paths with a dry run now publish as 23
skipped, nothing raised, no drafts left.
0.1.10
Added
client.user_events.stream(), the calling user's live events as Server-Sent
Events, parsed into typedUserEventvalues with keepalives consumed. It is
the only source of per-device collection progress; polling a collector task
gives the task, not each device. Verified live: a change set created and
deleted while subscribed arrived asCHANGE_SET_DELETEDwith its id. The
parser is pure and shared by both clients.client.cloud_accounts: seventeen operations for cloud collection sources,
list, create, update, delete, credential rotation, sub-account discovery
before and after creation, connectivity tests, the AWS assume-role external
id, and the region and environment lookups. Bodies are selected by cloud
type and the per-type fields are documented on each schema; secrets are
accepted on input and never returned. Verified live for the reads.
That completes the change-demo integration's second report. Everything Forward
serves for Predict, credentials, collectors, cloud sources and live events is
now an SDK call.
0.1.9
Added
client.snmp_credentials: list, create, update and delete a network's SNMP
credentials, which the published description leaves out although classic
devices reference them by id. Verified live with a credential created,
renamed and deleted. Secrets never come back: the community string and V3
passwords are returned as the numeric id of the stored secret.client.collector_binding: which collector serves a network, its connection
and health status, its version and update state, plus binding and unbinding.
The published/collector/statusis the deprecated busy flag; this is the
route a pre-flight wants. Verified live, where the collector reported
CONNECTEDandUNHEALTHY. ItscreatedAtis epoch milliseconds, which the
new response error caught on the first live call.snapshots.list(exclude_triggers=[...]), applied after the response since
Forward does not filter by trigger, with the limit applied after filtering so
the answer is not a short page.
Noted
- The second gap report from the change-demo integration, written against
0.1.7, listed the unchanged-corpus publish failure and the predicted-snapshot
default as still open. Both are fixed in 0.1.7 and verified again here on the
published package: 23 unchanged paths publish as 23 skipped, and predictions
are excluded by default. It also asked for a classic-device upsert, which the
SDK has had all along asclassic_devices.put_classic_devices()and the
per-deviceput_classic_device()andpatch_classic_device(), generated from
the published description under Forward's operation names.
0.1.8
Added
-
The rest of Forward Predict's surface, 51 more unpublished operations, so
everything the diff and change-set controllers serve is reachable. Nine
firewall object listings, which return the scoped identifiers the rule
writes expect. Four Forward AI assists. BGP advertisement injection,
withdrawal, restore and diffs. The change-set directory tree, with directory
paths percent-encoded for you. Andclient.snapshot_diff_detailsfor every
remaining diff view: check, file, device and cloud-object diffs, per-device
interface, ACL, NAT, routing, ARP and MAC entries, topology, VLANs and the
four connectivity views. All verified against a live instance of the current
build, writes included: a directory created, renamed and deleted; a BGP
route injected, reported asINJECTED, restored and gone.The curated
snapshot_diffsservice keeps the summaries and the connectivity
wait; the details service is generated from the description like every
published group. An NQE diff over the data model reaches the same per-device
differences with columns of your choosing, and the Predict page says when
each route is the better one.
Fixed
- A positional enum alias in the public models is resolved from the field that
uses it rather than from a literal number, which shifted the moment an inline
enum was added earlier in the description.
0.1.7
Added
-
Forward Predict, as five new groups of unpublished operations: 50 in all,
described from Forward's server source and verified against a live instance
of the current build. Requested by the change-demo integration, which had
been reaching them through a raw request helper.client.change_setscovers the rehearsal loop with a handle per change set:
create against a base snapshot, stage device commands as plain text, validate,
commit,predict_and_wait()for the processed predicted snapshot, checks, and
delete.client.snapshot_diffscompares two snapshots: subnet connectivity
withwait_for_subnet_connectivity()for the asynchronous computation,
vulnerability and routing-loop counts, their bidirectional views, a file
summary, andcounts()for every per-area count at once.
client.firewall_predictholds the structured security-rule edits PAN-OS
needs, since CLI-driven Predict does not work there.client.webhooksand
client.configurationround it out, withconfig_value()to read a
configuration response whatever its key.The traps a consumer met while working around these are encoded rather than
documented:noteis required on predict and commit, the bulk delete key is
changeSetIds, the create body carries nonetworkIdbecause Forward
rejects unknown properties, and the first connectivity read after a
prediction returns zeros that mean "not finished". See the new "Rehearsing a
change" page for the ones a signature cannot carry, including the global
configuration route reporting a default that the org route contradicts.Two claims in the consumer's notes were wrong and are corrected here: the
create body must not carrynetworkId, and an omitted webhook network list
is a 400 rather than a server crash. -
HAND_WRITTEN_TAGSis now one list, on the operation definitions module,
read by the service generator and the coverage test alike, so the two cannot
disagree about which groups are generated.
Fixed
-
The unpublished-endpoints page said the NQE execution request's sort and
filter fields were absent from the published description. They are in it. -
nqe.repo.publishno longer raises when nothing has changed. Forward
terminates its rejection with a full stop,User has no changes at the following paths: /a/q1, /a/q2., and the parser kept it, so the last path read
as/a/q2.and matched nothing. The caller then stripped every path but that
one and retried a commit Forward refused for the same reason, and the second
refusal escaped. Re-running an idempotent publisher with nothing to publish is
the normal case in a pipeline, and it reported failure. A single-path commit
was affected too, since that path is also the last one.A second refusal of the stripped set is now also read as a no-op rather than
raising, so a message this parser cannot read cannot turn a no-op into an
error again. Found by reading Forward's own source, which builds that string,
and confirmed on an instance of the current build: re-publishing a committed
query's own source returns a report with it skipped, commits nothing and
leaves no draft behind.
Changed
-
latest_processedandlatest_processed_idexclude predicted snapshots.
Forward creates and processes one for every Predict run, so on a network using
Predict the newest processed snapshot is very often a prediction rather than a
state the network was ever in, and basing a change set on one predicts a
change against a change. Passinclude_predicted=Truefor the old behaviour.The filter excludes
PREDICTrather than requiringCOLLECTION. A reprocessed
snapshot reportsREPROCESSand is real collected data, and on one live
network 20 of 43 processed snapshots were reprocessed; requiringCOLLECTION
would skip those and select the previous collection, which during a rehearsal
is the snapshot taken while the change was still applied. Reported by the
change-demo integration, which had hit exactly that.Confirmed against a Predict-enabled instance: on a network there, 4 of 5
processed snapshots were predictions, so the previous default picked one four
times in five.