Skip to content

Releases: forwardnetworks/forward-python-sdk

v0.1.16

Choose a tag to compare

@captainpacket captainpacket released this 17 Sep 15:42

[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's cloud_instances.gen. Closes a gap docs/snapshots.md had 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 as ForwardNotFoundError.

v0.1.15

Choose a tag to compare

@captainpacket captainpacket released this 16 Sep 01:09

[0.1.15] - 2026-09-16

Added

  • Connectivity tests, unpublished: client.connectivity_tests starts and stops
    an on-demand reachability/authentication probe against a classic device or a
    network endpoint (start/stop, one name or a DeviceSet, 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 a RootModel, so phase.root gets 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

Choose a tag to compare

@captainpacket captainpacket released this 12 Sep 15:52

[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 published LocationFilter union 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) and client.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(): the R_ 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_*_connections on 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() and remove_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

Choose a tag to compare

@captainpacket captainpacket released this 12 Sep 11:42

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 as OUTBOUND_CONNECTIONS,
    which gates webhook creation, and PROBE_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

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 21:33

Fixed

  • nqe.repo.publish with a dry run refused every clean change. Forward's dry
    run returns newErrors as 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: an ERROR refuses 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
    WARNING does not block and is returned on CommitReport.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

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 21:19

Fixed

  • nqe.repo.dry_run drops paths with nothing staged and retries, exactly as
    commit does. A dry run is the same request with a flag and Forward refuses
    it for the same reason, so publish(dry_run_snapshot_id=...) raised on an
    unchanged corpus where publish() 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

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 20:58

Added

  • client.user_events.stream(), the calling user's live events as Server-Sent
    Events, parsed into typed UserEvent values 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 as CHANGE_SET_DELETED with 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

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 20:49

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/status is the deprecated busy flag; this is the
    route a pre-flight wants. Verified live, where the collector reported
    CONNECTED and UNHEALTHY. Its createdAt is 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 as classic_devices.put_classic_devices() and the
    per-device put_classic_device() and patch_classic_device(), generated from
    the published description under Forward's operation names.

0.1.8

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 20:33

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. And client.snapshot_diff_details for 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 as INJECTED, restored and gone.

    The curated snapshot_diffs service 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

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 18:00

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_sets covers 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_diffs compares two snapshots: subnet connectivity
    with wait_for_subnet_connectivity() for the asynchronous computation,
    vulnerability and routing-loop counts, their bidirectional views, a file
    summary, and counts() for every per-area count at once.
    client.firewall_predict holds the structured security-rule edits PAN-OS
    needs, since CLI-driven Predict does not work there. client.webhooks and
    client.configuration round it out, with config_value() to read a
    configuration response whatever its key.

    The traps a consumer met while working around these are encoded rather than
    documented: note is required on predict and commit, the bulk delete key is
    changeSetIds, the create body carries no networkId because 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 carry networkId, and an omitted webhook network list
    is a 400 rather than a server crash.

  • HAND_WRITTEN_TAGS is 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.publish no 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_processed and latest_processed_id exclude 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. Pass include_predicted=True for the old behaviour.

    The filter excludes PREDICT rather than requiring COLLECTION. A reprocessed
    snapshot reports REPROCESS and is real collected data, and on one live
    network 20 of 43 processed snapshots were reprocessed; requiring COLLECTION
    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.