apple / apple/app-store-server-library-node
Subscription status response validators omit validation of data and nested lastTransactions
- Dominant language
- TypeScript
- Stars
- 382
- Forks
- 79
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 9
Description
### Description
`StatusResponseValidator` checks `environment`, `bundleId` and `appAppleId`, but never validates `data`, which is declared as `SubscriptionGroupIdentifierItem[]`.
There is a second gap in the nested model: `SubscriptionGroupIdentifierItemValidator` checks only `subscriptionGroupIdentifier` and never validates `lastTransactions`, which is declared as `LastTransactionsItem[]`.
Consequently, the response validator accepts a non-array `data` value, malformed subscription-group entries and malformed transaction entries. Connecting `StatusResponseValidator` to the existing subscription-group validator alone would not fully address the problem, because that validator also omits its nested array.
### Reproduction
From the repository root, after building the package:
```js
const {
StatusResponseValidator,
} = require('./dist/models/StatusResponse.js');
const {
SubscriptionGroupIdentifierItemValidator,
} = require('./dist/models/SubscriptionGroupIdentifierItem.js');
const {
LastTransactionsItemValidator,
} = require('./dist/models/LastTransactionsItem.js');
const responseValidator = new StatusResponseValidator();
const groupValidator = new SubscriptionGroupIdentifierItemValidator();
const transactionValidator = new LastTransactionsItemValidator();
console.log(responseValidator.validate({ data: 'not-an-array' }));
// true
console.log(groupValidator.validate({ lastTransactions: 'not-an-array' }));
// true
const invalidTransaction = { signedTransactionInfo: 123 };
console.log(responseValidator.validate({
data: [{
subscriptionGroupIdentifier: '123',
lastTransactions: [invalidTransaction],
}],
}));
// true
console.log(transactionValidator.validate(invalidTransaction));
// false
```
### Expected behavior
When present, `data` must be an array of valid subscription-group items. Within each group, `lastTransactions`, when present, must be an array of valid transaction items. Invalid nested values should cause validation of the containing response to return false.
Omitted optional fields should remain accepted, consistent with the current model definitions.
### Impact
`AppStoreServerAPIClient.getAllSubscriptionStatuses` uses `StatusResponseValidator`. Its runtime validation therefore does not enforce the declared structure of the subscription data returned to callers. Downstream code may receive incompatible values despite a successful client validation result.
This concerns structural validation of the API response. Cryptographic verification of the signed transaction and renewal payloads remains a separate operation.
### Suggested change
- In `StatusResponseValidator`, check that a present `data` value is an array and validate each entry with `SubscriptionGroupIdentifierItemValidator`.
- In `SubscriptionGroupIdentifierItemValidator`, check that a present `lastTransactions` value is an array and validate each entry with `LastTransactionsItemValidator`.
- Add regression coverage for invalid array types, invalid nested fields and valid nested responses.
Contributor guide
Research direction
Start by inspecting the validators in dist/models/StatusResponse.js, dist/models/SubscriptionGroupIdentifierItem.js, and dist/models/LastTransactionsItem.js after building the package. Trace how optional arrays and nested validators are handled, then add regression coverage for invalid array types, malformed nested entries, and valid omitted or nested fields. Done means invalid nested responses return false while valid responses and omitted optional fields remain accepted.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100