Skip to content

Commit 3cd9696

Browse files
authored
Merge pull request #177 from signnow/callback-history-id
Add GetCallbacksBySubscriptionIdAsync - webhook callback event history related to subscription ID
2 parents 3c01582 + 9e0191a commit 3cd9696

23 files changed

Lines changed: 506 additions & 88 deletions

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ updates:
66
directory: "/"
77
schedule:
88
interval: "weekly"
9-
target-branch: main
9+
target-branch: develop
1010
commit-message:
1111
prefix: "ci: "

.github/workflows/build_and_test.yml

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,6 @@ on:
1818
- '**.md'
1919
tags-ignore:
2020
- '**'
21-
pull_request_target:
22-
branches:
23-
- 'main'
24-
- 'develop'
25-
paths-ignore:
26-
- '**.md'
27-
tags-ignore:
28-
- '**'
2921

3022
env:
3123
COREHOST_TRACE: false
@@ -37,6 +29,11 @@ env:
3729
# Do not generate summary otherwise it leads to duplicate errors in build log
3830
DOTNET_BUILD_ARGS: /consoleloggerparameters:NoSummary /property:GenerateFullPaths=true
3931

32+
TEST_CREDITS_JSON: ${{ secrets.TEST_CREDITS_JSON }}
33+
SONAR_SECRET: ${{ secrets.SONAR_SECRET }}
34+
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
35+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
36+
4037
defaults:
4138
run:
4239
shell: pwsh
@@ -62,11 +59,11 @@ jobs:
6259
- { name: 'Windows .NET 4.6', os: windows-latest, framework: 'net462', net-sdk: '8.0.x', target: 'net462' }
6360

6461
steps:
65-
- uses: actions/checkout@v4
62+
- uses: actions/checkout@v6
6663
with:
67-
fetch-depth: 1
64+
fetch-depth: 0
6865
# For pull_request_target (dependabot), checkout the PR head SHA
69-
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }}
66+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
7067

7168
- name: Get SDK Version
7269
id: props
@@ -77,18 +74,18 @@ jobs:
7774
Write-Host "✓ Found SignNow.NET SDK project version: $Version"
7875
7976
- name: Setup JDK 17 (SonarQube requirement)
80-
uses: actions/setup-java@v4
77+
uses: actions/setup-java@v5
8178
with:
8279
distribution: 'zulu'
8380
java-version: '17'
8481

8582
- name: Setup .NET SDK
86-
uses: actions/setup-dotnet@v4
83+
uses: actions/setup-dotnet@v5
8784
with:
8885
dotnet-version: ${{ matrix.net-sdk }}
8986

9087
- name: Setup Nuget Cache
91-
uses: actions/cache@v4
88+
uses: actions/cache@v5
9289
id: nuget-cache
9390
with:
9491
path: ~/.nuget
@@ -102,12 +99,14 @@ jobs:
10299
run: dotnet restore -v:n
103100

104101
- name: Configure signNow API
105-
run: echo '${{ secrets.TEST_CREDITS_JSON }}' >> ${{ github.workspace }}/api-eval.signnow.com.json
102+
run: |
103+
$outPath = Join-Path $Env:GITHUB_WORKSPACE 'api-eval.signnow.com.json'
104+
[IO.File]::WriteAllText($outPath, $Env:TEST_CREDITS_JSON)
106105
107106
- name: Get SonarQube Project Key
108107
id: sonar
109108
run: |
110-
$SonarConfigPath = "${{ github.workspace }}/SonarQube.Analysis.xml"
109+
$SonarConfigPath = Join-Path $Env:GITHUB_WORKSPACE 'SonarQube.Analysis.xml'
111110
if (Test-Path $SonarConfigPath) {
112111
[xml]$SonarConfig = Get-Content $SonarConfigPath
113112
$ProjectKey = $SonarConfig.SonarQubeAnalysisProperties.Property | Where-Object { $_.Name -eq "sonar.projectKey" } | Select-Object -ExpandProperty '#text'
@@ -121,7 +120,7 @@ jobs:
121120
} else {
122121
Write-Warning "SonarQube configuration file not found: $SonarConfigPath"
123122
}
124-
123+
125124
- name: SonarQube begin
126125
if: steps.sonar.outputs.has-project-key == 'true'
127126
run: |
@@ -130,8 +129,8 @@ jobs:
130129
/s:${{ github.workspace }}/SonarQube.Analysis.xml `
131130
/v:"${{ steps.props.outputs.version }}" `
132131
/d:sonar.projectBaseDir="${{ github.workspace }}" `
133-
/d:sonar.token="${{ secrets.SONAR_SECRET }}" `
134-
/d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}" `
132+
/d:sonar.token="${{ env.SONAR_SECRET }}" `
133+
/d:sonar.host.url="${{ env.SONAR_HOST_URL }}" `
135134
/d:sonar.scanner.skipJreProvisioning=true
136135
137136
- name: Run Tests on ${{ matrix.framework }} for TargetFramework ${{ matrix.target }} with Coverage
@@ -145,22 +144,22 @@ jobs:
145144
dotnet build SignNow.Net.Test --configuration Debug --no-incremental `
146145
--framework ${{ matrix.framework }} `
147146
${{ env.DOTNET_BUILD_ARGS }}
148-
147+
149148
dotnet test SignNow.Net.Test --configuration Debug --no-build `
150149
--framework ${{ matrix.framework }} `
151150
--logger:trx --results-directory ./SignNow.Net.Test/TestResults `
152151
/p:CollectCoverage=true
153152
154153
- name: Save Code Coverage Results
155-
uses: actions/upload-artifact@v4
154+
uses: actions/upload-artifact@v6
156155
with:
157156
name: CoverageReports-${{ runner.os }}-${{ matrix.framework }}.zip
158157
path: ${{ env.COVERAGE_PATH }}/**/coverage*
159-
158+
160159
- name: SonarQube end
161160
if: steps.sonar.outputs.has-project-key == 'true'
162161
continue-on-error: true
163-
run: dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_SECRET }}"
162+
run: dotnet-sonarscanner end /d:sonar.token="${{ env.SONAR_SECRET }}"
164163

165164
- name: Test Release Notes parser
166165
if: (runner.os == 'macOS' || runner.os == 'Linux')
@@ -177,12 +176,10 @@ jobs:
177176
- name: Upload Code Coverage Report (Codecov.io)
178177
if: env.CODECOV_TOKEN != ''
179178
continue-on-error: true
180-
env:
181-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
182179
uses: codecov/codecov-action@v5
183180
with:
184181
name: ${{ runner.os }}-codecov-${{ matrix.framework }}
185182
flags: ${{ runner.os }},${{ matrix.target }}
186-
token: ${{ secrets.CODECOV_TOKEN }}
183+
token: ${{ env.CODECOV_TOKEN }}
187184
files: ${{ env.COVERAGE_PATH }}/${{ matrix.framework }}/coverage.${{ matrix.framework }}.opencover.xml
188185
fail_ci_if_error: false

.github/workflows/release.yml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ jobs:
1818

1919
defaults:
2020
run:
21-
shell: pwsh
21+
shell: bash
2222

2323
steps:
24-
- uses: actions/checkout@v4
24+
- uses: actions/checkout@v6
2525

2626
- name: Setup .NET 8
27-
uses: actions/setup-dotnet@v4
27+
uses: actions/setup-dotnet@v5
2828
with:
2929
dotnet-version: |
3030
7.0.x
3131
8.0.x
3232
3333
- name: Setup Nuget Cache
34-
uses: actions/cache@v4
34+
uses: actions/cache@v5
3535
id: nuget-cache
3636
with:
3737
path: ~/.nuget
@@ -53,8 +53,10 @@ jobs:
5353

5454
- name: Create Release
5555
uses: ncipollo/release-action@v1
56+
env:
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5658
with:
57-
token: ${{ secrets.GITHUB_TOKEN }}
59+
token: ${{ env.GITHUB_TOKEN }}
5860
name: signNow .Net SDK v${{ steps.get-version.outputs.VERSION }}
5961
tag: ${{ steps.get-version.outputs.VERSION }}
6062
bodyFile: ${{ github.workspace }}/release-notes.txt
@@ -64,7 +66,10 @@ jobs:
6466

6567
- name: Publish Nuget Package
6668
working-directory: ${{ github.workspace }}/SignNow.Net/bin/Publish
69+
shell: pwsh
70+
env:
71+
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
6772
run: |
68-
dotnet nuget push SignNow.Net.${{ steps.get-version.outputs.VERSION }}.nupkg \
69-
-k ${{ secrets.NUGET_TOKEN }} \
70-
-s https://api.nuget.org/v3/index.json
73+
dotnet nuget push SignNow.Net.${{ steps.get-version.outputs.VERSION }}.nupkg `
74+
--api-key ${{ env.NUGET_TOKEN }} `
75+
--source https://api.nuget.org/v3/index.json

AGENTS.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# SignNow .NET SDK - Architectural Context & Global Guidance
2+
3+
This file establishes the architectural philosophy and coding standards for SignNow .NET SDK.
4+
Applies to every agent session.
5+
6+
## 1. System Identity
7+
**Role:** Principal Software Architect and Technical Archaeologist of a Fortune 500 tech company
8+
**Core Stack:**
9+
- C# SDK built with multi-targeted MSBuild projects (`net462`, `netstandard2.0`, `netstandard2.1`, current modern .NET);
10+
- HttpClient transport wrapped by `ISignNowClient`/`IHttpContentAdapter`;
11+
- Newtonsoft.Json serialization;
12+
- MSTest/xUnit-style suites under `SignNow.Net.Test`; shared configuration via `Directory.Build.props`, `SignNow.props`, and `netfx.props`.
13+
**Philosophy:**
14+
"The SDK as a Bridge" - This library is the trusted bridge between customer applications and SignNow's API. Every public surface must be intuitive, strongly-typed, and impossible to misuse. Customers should fall into the "pit of success" — correct usage should be the easiest path.
15+
*Metaphor: "The Trusted Courier"* - every SDK call should feel like handing a critical contract to a concierge who takes the direct, recommended route with zero delays or detours.
16+
17+
## 2. Strategic Vision
18+
Deliver a robust, frictionless SDK so developers can add the NuGet package, configure `SignNowContext`, and issue their first API call within minutes. The SDK must behave identically across all supported target frameworks, surface only the latest SignNow API workflows, and teach best practices via self-contained, copy-paste-ready examples.
19+
This SDK serves as the **official .NET integration point** for SignNow's electronic signature platform. Technical implications:
20+
21+
- **Broad Compatibility:** Must compile and run identically across .NET Framework 4.6.2, .NET Standard 2.0/2.1, and modern .NET. No platform-specific APIs without conditional compilation.
22+
- **Zero Friction Integration:** Customers must be able to add the NuGet package, configure `SignNowContext`, and make their first API call within minutes.
23+
- **Copy-Paste Ready Examples:** The `/Examples` project is customer-facing documentation. Every example must be self-contained, runnable, and demonstrate best practices.
24+
- **Single Path Principle:** When SignNow API offers multiple ways to accomplish a task, the SDK exposes only the latest/recommended approach. No legacy API endpoint wrappers.
25+
26+
## 3. Architectural Boundaries
27+
```plaintext
28+
+---------------------------+
29+
| Consumer Apps / Examples |
30+
+-------------+-------------+
31+
|
32+
v
33+
+---------------------------+
34+
| Public SDK Surface |
35+
| (SignNowContext, DTOs) |
36+
+-------------+-------------+
37+
|
38+
v
39+
+---------------------------+
40+
| Domain Services & Models |
41+
| (Service/, _Internal/Model)
42+
+-------------+-------------+
43+
|
44+
v
45+
+---------------------------+
46+
| Infrastructure & Transport|
47+
| (_Internal/Infrastructure)|
48+
+-------------+-------------+
49+
|
50+
v
51+
+---------------------------+
52+
| SignNow REST API |
53+
+---------------------------+
54+
```
55+
56+
### Layer Rules (Access Matrix)
57+
| Layer | CAN Access | CANNOT Access |
58+
|-------|------------|---------------|
59+
| Consumer Apps & `SignNow.Net.Examples` | Public SDK Surface | Domain internals, infrastructure helpers |
60+
| Public SDK Surface (`SignNowContext`, `Interfaces/`, DTOs) | Domain Services & Models | Infrastructure plumbing, HTTP adapters |
61+
| Domain Services & Models (`Service/`, `_Internal/Model`, mappers) | Infrastructure & Transport | Consumer utilities, UI concerns |
62+
| Infrastructure & Transport (`_Internal/Infrastructure`, Helpers, adapters) | SignNow REST API, serialization libraries | Consumer apps, presentation layers |
63+
64+
### Layer Constraints
65+
66+
- **Public API Surface:** All public types must have XML documentation. No breaking changes without major version bump.
67+
- **Service Layer:** Services are stateless. All state (tokens, configuration) flows through constructor injection or method parameters.
68+
- **Infrastructure Layer:** HTTP concerns stay here. Services never see `HttpResponseMessage` or status codes directly.
69+
70+
## 4. Data Flow & Patterns
71+
```plaintext
72+
Caller -> SignNowContext -> IService interface -> Domain Service
73+
-> Request builder / validator -> IHttpContentAdapter -> HTTP pipeline
74+
-> SignNow REST API -> Response translator -> DTO -> Caller
75+
```
76+
- Orchestration stays thin at the surface;
77+
- All rules live in services;
78+
- Transport remains abstract and testable;\
79+
- Serialization/deserialization never leaks into consumer-facing layers.
80+
81+
## 5. Development Constraints
82+
* **Tech Stack Rules:**
83+
- Preserve all existing target frameworks and MSBuild property imports;
84+
- Guard any platform-specific API behind conditional compilation;
85+
- Rely on the provided HttpClient abstractions and Newtonsoft.Json converters;
86+
- Do not introduce new external SaaS dependencies.
87+
* **State Management:**
88+
- Keep `SignNowContext` and services stateless aside from injected tokens;
89+
- Prefer async/await end-to-end with no sync-over-async;
90+
- Cache credentials or documents only through approved adapters;
91+
- Never store mutable state in statics except immutable configuration.
92+
* **Critical Data Constraint:**
93+
- Treat tokens, invites, document payloads, and signer identifiers as sensitive—never log raw values;
94+
- Redact PII in diagnostics;
95+
- Stream large documents to limit memory pressure;
96+
- Normalize and persist timestamps in UTC;
97+
- Respect API-provided idempotency keys when available;
98+
- All API errors surface as `SignNowException` or its derivatives;
99+
- Exception messages must be actionable for customers.
100+
* **Documentation Rules:**
101+
- All public types and members require XML documentation
102+
- Use `<example>` tags for common usage patterns
103+
- Parameter descriptions must explain valid values and constraints
104+
105+
## 6. Anti-Patterns (Forbidden)
106+
-**YAGNI violations (You Aren't Gonna Need It):** Don't add functionality until it's actually needed.
107+
- No "just in case" features, configurations, or abstractions
108+
- No future-proofing for hypothetical requirements
109+
- No generic solutions when a specific one solves the current problem
110+
- Three similar lines of code is better than premature abstraction
111+
-**Endpoint Forking:** Never expose multiple SDK paths for deprecated API endpoints; always guide callers through the single, recommended SignNow flow.
112+
-**Platform Drift:** Introducing APIs unavailable on `net462`/`netstandard2.x` without conditional compilation or fallbacks is prohibited.
113+
-**Async Blocking & Hidden Threads:** No `.Result`, `.Wait()`, or ad-hoc threads inside SDK services—stay purely async through the supplied HttpClient infrastructure.
114+
115+
## 7. Critical File Locations
116+
```plaintext
117+
.
118+
├─ AGENTS.md
119+
├─ SignNow.Net.sln ← SACRED (DO NOT MODIFY)
120+
├─ Directory.Build.props ← SACRED (DO NOT MODIFY)
121+
├─ SignNow.props ← SACRED (DO NOT MODIFY)
122+
├─ netfx.props ← SACRED (DO NOT MODIFY)
123+
├─ .editorconfig ← SACRED (Coding conventions source of truth)
124+
├─ SignNow.Net/
125+
│ ├─ SignNowContext.cs ← SACRED (Main DI entry point / Composition root)
126+
│ ├─ Interfaces/
127+
│ ├─ Service/
128+
│ ├─ _Internal/
129+
│ │ ├─ Infrastructure/
130+
│ │ └─ Model/
131+
│ └─ Extensions/
132+
├─ SignNow.Net.Examples/
133+
│ ├─ ExamplesBase.cs ← SACRED (DO NOT MODIFY)
134+
│ └─ Scenario folders (customer-facing)
135+
├─ SignNow.Net.Test/
136+
│ ├─ AcceptanceTests/
137+
│ ├─ FeatureTests/
138+
│ └─ UnitTests/
139+
└─ logs/ (diagnostics only)
140+
```
141+
142+
---
143+
144+
Last Updated: 2026-02-03
145+
146+
Maintained by: AI Agents under human supervision

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com)
55
and this project adheres to [Semantic Versioning](http://semver.org).
66

77
## [Unreleased] - TBD
8+
### Added
9+
- Event Subscriptions & Webhooks:
10+
- Get Callbacks History by ID: webhook callback event history related to subscription ID with advanced filtering and sorting capabilities
811

912
## [1.4.0] - 2026-01-13
1013
### Added

0 commit comments

Comments
 (0)